কোনও লিঙ্কযুক্ত তালিকা থেকে কোনও আইটেম সরানোর সঠিক উপায়


10

এই স্ল্যাশডট সাক্ষাত্কারে লিনাস টরভাল্ডস উদ্ধৃত হয়েছে:

আমি অনেক লোককে দেখেছি যারা "পূর্ব" এন্ট্রি ট্র্যাক করে এককভাবে সংযুক্ত তালিকার তালিকা মুছুন এবং তারপরে এন্ট্রি মুছতে, এমন কিছু করে

if (prev)
  prev-> next = enter-> next;
অন্য
  তালিকা_সামগ্রী = এন্ট্রি-> পরবর্তী;

এবং যখনই আমি এর মতো কোড দেখি, আমি কেবল "এই ব্যক্তি পয়েন্টার বোঝে না" go এবং দুঃখজনকভাবে এটি খুব সাধারণ।

পয়েন্টার বোঝে এমন লোকেরা কেবল "এন্ট্রি পয়েন্টারটিতে পয়েন্টার" ব্যবহার করে এবং তালিকা_ইডের ঠিকানা দিয়ে এটি সূচনা করে। এবং তারপরে তারা তালিকাটি অতিক্রম করে, কেবল কোনও "* পিপি = এন্ট্রি->" পরবর্তী করে কোনও শর্ত ছাড়াই তারা প্রবেশ সরিয়ে ফেলতে পারে।

পিএইচপি বিকাশকারী হিসাবে আমি এক দশক আগে বিশ্ববিদ্যালয়ে সি পরিচয় হওয়ার পর থেকে পয়েন্টারগুলিকে স্পর্শ করি নি । তবে আমি অনুভব করি যে এটি এমন এক ধরণের পরিস্থিতি যার সাথে আমার অন্তত পরিচিত হওয়া উচিত। লিনাস কী সম্পর্কে কথা বলছে? সত্য কথা বলতে গেলে, যদি আমাকে লিঙ্কযুক্ত তালিকাটি কার্যকর করতে এবং কোনও আইটেম সরাতে বলা হয়, তবে উপরের 'ভুল' উপায়টি আমি এর পথে যাব। লিনাস সবচেয়ে ভাল বলে তাই কোড করার জন্য আমার কী জানা দরকার?

আমি স্ট্যাক ওভারফ্লো না করেই এখানে জিজ্ঞাসা করছি কারণ প্রোডাকশন কোডে আমার আসলে এটির সমস্যা নেই।


1
তিনি যা বলছেন তা হ'ল আপনাকে যখন prevপুরো নোডটি সংরক্ষণ করার পরিবর্তে লোকেশনটির অবস্থান সংরক্ষণ করতে হবে তখন আপনি কেবলমাত্র সেই অবস্থানটি সংরক্ষণ করতে পারেন prev.next, যেহেতু 'আপনার আগ্রহী একমাত্র জিনিস a এবং যদি আপনি এটি করেন তবে আপনি মূর্খতা এড়ান if, যেহেতু এখন আপনার কাছে list_headকোনও নোডের বাইরে থেকে পয়েন্টার হওয়ার মতো বিশ্রী ঘটনা নেই । তালিকার শিরোনামের পয়েন্টারটি পরে শব্দার্থগতভাবে পরবর্তী নোডের পয়েন্টারের সমান হয়।
নিয়মিত

@ আরদৌস: আমি দেখছি, ধন্যবাদ কেন একটি মন্তব্য? এটি একটি সংক্ষিপ্ত, পরিষ্কার এবং আলোকিত উত্তর।
dotancohen

@ উর্ডস সেই কোড স্নিপেটের সাথে জড়িত সমস্ত কিছুই একটি পয়েন্টার, সুতরাং তার বিন্দুটিতে কোনও পয়েন্টার সংরক্ষণ করে বনাম পুরো নোড সংরক্ষণ করার সাথে কিছুই করতে পারে না।
ডোভাল

উত্তর:


9

আমার L331 এমএস পেইন্ট দক্ষতা ব্যবহার:

এখানে চিত্র বর্ণনা লিখুন

মূল সমাধান মাধ্যমে নোড বিন্দু হয় curr। সেক্ষেত্রে আপনি পরের নোডের currমুছার মানটি আছে কিনা তা পরীক্ষা করে দেখুন এবং যদি তাই হয় তবে currনোড nextপয়েন্টারটি পুনরায় সেট করুন । সমস্যাটি হ'ল এমন কোনও নোড নেই যা তালিকার শীর্ষে নির্দেশ করে। তার মানে এটি পরীক্ষা করার জন্য একটি বিশেষ কেস থাকতে হবে।

পরিবর্তে লিনাস (সম্ভবত) যা প্রস্তাব দেয় তা হ'ল পয়েন্টারটিকে বর্তমান পরীক্ষিত নোডে সংরক্ষণ করা নয়, বরং পয়েন্টারটিকে বর্তমান নোডে (লেবেলযুক্ত pp) সংরক্ষণ করা। অপারেশনটি একই - যদি ppপয়েন্টারটি সঠিক মান সহ কোনও নোডের দিকে নির্দেশ করে তবে আপনি ppপয়েন্টারটি পুনরায় সেট করুন ।

পার্থক্যটি তালিকার একেবারে শুরুতে আসে। যখন কোনও নোড নেই যা তালিকার প্রধানকে নির্দেশ করে, সেখানে আসলে তালিকার শীর্ষে একটি পয়েন্টার রয়েছে। এবং এটি নোডের ঠিক একই পয়েন্টার যেমনটি অন্য নোডের nextপয়েন্টার। অতএব তালিকাটি শুরুর জন্য বিশেষ ধারাটির প্রয়োজন নেই।


আহ আমি এখন দেখছি .... আপনি প্রতিদিন নতুন কিছু শিখুন।
লরেন্স আইলো

1
আমি মনে করি আপনি জিনিসগুলি সঠিকভাবে বর্ণনা করেছেন, তবে আমি পরামর্শ দেব যে সঠিক সমাধানটি list_headকোনও nextনোডের সাথে এমন কোনও কিছুতে নির্দেশ করা উচিত যা প্রথম আসল ডেটা আইটেমটির দিকে নির্দেশ করে (এবং prevসেই একই ডামি অবজেক্টে সূচনা করেছিল)। আমি prevভিন্ন ধরণের কিছুতে ইঙ্গিত করার ধারণাটি পছন্দ করি না , যেহেতু এই জাতীয় কৌশলগুলি এলিয়াসিংয়ের মাধ্যমে অনির্ধারিত আচরণটি প্রবর্তন করতে পারে এবং কোডটিকে কাঠামোর বিন্যাসে অযথা সংবেদনশীল করে তুলতে পারে।
সুপারক্যাট

@ সুপের্যাট ঠিক এটাই কথা। prevনোডের দিকে নির্দেশ করার পরিবর্তে এটি পয়েন্টারগুলিকে নির্দেশ করে। এটি সর্বদা একই ধরণের কিছুতে নির্দেশ করে, একটি নোডের কাছে পয়েন্টার। আপনার পরামর্শটি মূলত একই রকম - prev" nextনোড সহ" কিছুতে নির্দেশ করুন । আপনি যদি শেলটি ফেলে দেন তবে আপনি কেবল প্রাথমিক list_headপয়েন্টারটি পাবেন। বা অন্য কথায় - এমন কিছু যা কেবলমাত্র পরবর্তী নোডের পয়েন্টার রেখে সংজ্ঞায়িত হয়, শব্দার্থগতভাবে নোডের সাথে পয়েন্টারের সমান।
সাধারণ

@ আরদৌস: এটি অর্থবোধ করে, যদিও এটি এটি অনুমান করে list_headএবং nextএকই ধরণের "পয়েন্টার" ধারণ করে। সি তে কোনও সমস্যা নয়, সম্ভবত, তবে সম্ভবত সি ++ এ সমস্যাযুক্ত।
সুপারক্যাট

@ সুপের্যাট আমি সবসময়ই ধরে নিয়েছিলাম যে এটি একটি লিঙ্কযুক্ত তালিকার ভাষা-অজ্ঞাত "নীতিগত" উপস্থাপনা। তবে আমি সত্যই সি এবং সি ++ এর মধ্যে পার্থক্য তৈরি করে কিনা এবং সেখানে স্ট্যান্ডার্ড বাস্তবায়নগুলি কি কি তা বিচার করার পক্ষে আমি যথেষ্ট দক্ষ না।
16

11

এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন

কোড উদাহরণ

// ------------------------------------------------------------------
// Start by pointing to the head pointer.
// ------------------------------------------------------------------
//    (next_ptr)
//         |
//         v
// [head]----->[..]----->[..]----->[..]----->[to_remove]----->[....]
Node** next_ptr = &list->head;

// ------------------------------------------------------------------
// Search the list for the matching entry.
// After searching:
// ------------------------------------------------------------------
//                                  (next_ptr)
//                                       |
//                                       v
// [head]----->[..]----->[..]----->[..]----->[to_remove]----->[next]
while (*next_ptr != to_remove) // or (*next_ptr)->val != to_remove->val
{
    Node* next_node = *next_ptr
    next_ptr = &next_node->next;
}

// ------------------------------------------------------------------
// Dereference the next pointer and set it to the next node's next
// pointer.
// ------------------------------------------------------------------
//                                           (next_ptr)
//                                                |
//                                                v
// [head]----->[..]----->[..]----->[..]---------------------->[next]
*next_ptr = to_remove->next;

নোডটি ধ্বংস করতে যদি আমাদের কিছু যুক্তি প্রয়োজন হয় তবে আমরা কেবল শেষে একটি লাইন কোড যুক্ত করতে পারি:

// Deallocate the node which is now stranded from the list.
free(to_remove);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.