2013-05-08 6 views
8

मैं FreeBSD से sys/queue.h का अध्ययन कर रहा हूँ और मैं एक सवाल है: इस प्रकारsys/queue.h में दोगुनी लिंक की गई सूची पिछले अगले तत्व का पता क्यों बनाए रखती है?

sys/queue.h में, LIST_ENTRY परिभाषित किया गया है:

#define LIST_ENTRY(type)      \ 
struct {        \ 
    struct type *le_next; /* next element */   \ 
    struct type **le_prev; /* address of previous next element */ \ 
} 

ऐसा क्यों है पिछले अगले तत्व का पता बनाए रखने करता है (struct type **le_prev) पिछले elment की तरह struct type *le_prev की बजाय?

उत्तर

8

आप शुरू से ही queue.h फ़ाइल को पढ़ने होता हैं, तो आप मिल गया है हो सकता है निम्नलिखित टिप्पणी:

* A list is headed by a single forward pointer (or an array of forward 
* pointers for a hash table header). The elements are doubly linked 
* so that an arbitrary element can be removed without a need to 
* traverse the list. New elements can be added to the list before 
* or after an existing element or at the head of the list. A list 
* may only be traversed in the forward direction. 

इतना सूची है, जो हे (1) प्रविष्टि और विलोपन, लेकिन केवल आगे प्रदान करता है ट्रेवर्सल। इसे प्राप्त करने के लिए, आपको केवल पहले के पॉइंटर के संदर्भ की आवश्यकता है, जो कि लागू है।

+0

क्या आपका मतलब है कि यह कार्यान्वयन पिछड़ा ट्रैवर्सल को रोकने के साथ-साथ ओ (1) सम्मिलन और हटाना भी है? –

+0

@YanzheChen (रैखिक) सूची संचालन की जटिलता तब नहीं बदलेगी जब आप एक पॉइंटर का उपयोग करते हैं और डबल पॉइंटर पिछड़ा ट्रैवर्सल को रोकता नहीं है। मुझे लगता है, महत्वपूर्ण हिस्सा "या आगे पॉइंटर्स की एक सरणी" है; जब ऐसी (हैश) तालिका होती है, तो पिछली पॉइंटर का पता संग्रहीत होने पर हटाने को सस्ता होता है। – ensc

+0

@ensc मैंने इसे पढ़ा [पोस्ट] (http://stackoverflow.com/questions/9362896/deleting-any-node-from-a-single-linked-list-when-only-pointer-to-that-node- is-gi) और समझते हैं कि सिंगल-लिंक्ड सूची में हटाना ओ (1) में प्राप्त किया जा सकता है यदि यह पूंछ नोड नहीं है। लेकिन क्यों डबल पॉइंटर ** ** ** पिछड़ा ट्रैवर्सल क्यों रोकता है? पिछड़ा ट्रैवर्सल कैसे करें? और मैं समझ नहीं पा रहा हूं ** महत्वपूर्ण भाग ** आपने या तो उल्लेख किया है। क्या आप इसे अधिक जानकारी में समझा सकते हैं? –

0

मुझे समझाने की कोशिश करें। असल में **le_prev* sys/queue.h से insert_before द्वारा परिभाषित सूची में ablity प्रदान करता है कि आगे की सूची नहीं कर सकते हैं। insert_before की तुलना में, insert_after दोनों को आगे-सूची या सूची में अच्छी तरह से कार्यान्वित किया जा सकता है। तो सूची अधिक कार्यात्मक है।

insert_before(entry* list_elem, entry* elem, type val) 
{ 
    elem->next = list_elem; 
    *(list->prev) = elem; 
    elem->prev = *(list->prev); 
    list_elem->prev = elem->next; 
} 
insert_after(entry* list_elem, entry* elem, type val) 
{ 
    if(((elem)->next= (list_elem)->next) != NULL) { 
     (elem_list)->next->prev = &(elem)->next; 
    } 
    (list_elem)->next = elem; 
    elem->prev = &(list_elem)->next; 
} 
संबंधित मुद्दे