Data structure C # Notes-two-way linked list (dblinklist)

Source: Internet
Author: User

This is the continuation of the linklist of the data structure C # version note-a linear table (data structure). For bidirectional links, except for the next attribute, the Prev attribute is also used to indicate the forward node. dbnode is defined as follows:

Namespace linear table {public class dbnode <t> {private t data; private dbnode <t> Prev; private dbnode <t> next; Public dbnode (t data, dbnode <t> next, dbnode <t> PREV) {This. data = data; this. next = next; this. prev = Prev;} public dbnode (t data, dbnode <t> next) {This. data = data; this. next = next; this. prev = NULL;} public dbnode (dbnode <t> next) {This. data = default (t); this. next = next; this. prev = NULL;} public dbnode (t data) {This. data = data; this. next = NULL; this. prev = NULL;} public dbnode () {DATA = default (t); next = NULL; Prev = NULL;} public t data {set {This. data = value;} get {return this. data ;}} public dbnode <t> Prev {get {return Prev;} set {Prev = value ;}} public dbnode <t> next {get {return next ;} set {next = value ;}}}}

The insert operation for double-stranded tables is a little more complex, as shown below:

Similarly, for the delete operation, the prev point must also be processed.

Complete implementation of dblinklist <t>:

Using system; using system. text; namespace linear table {public class dblinklist <t>: ilistds <t> {private dbnode <t> head; Public dbnode <t> head {get {return head ;} set {head = value ;}} public dblinklist () {head = NULL ;} /// <summary> /// class indexer /// </Summary> /// <Param name = "Index"> </param> /// <returns> </returns> Public t this [int Index] {get {return this. getitemat (INDEX) ;}/// <summary> /// return ticket Length of the linked list /// </Summary> /// <returns> </returns> Public int count () {dbnode <t> P = head; int Len = 0; while (P! = NULL) {Len ++; P = P. next;} return Len;} // <summary> // clear // </Summary> Public void clear () {head = NULL ;} /// <summary> /// whether it is null /// </Summary> /// <returns> </returns> Public bool isempty () {return head = NULL ;} /// <summary> /// add an element to the end /// </Summary> /// <Param name = "item"> </param> Public void append (T item) {dbnode <t> d = new dbnode <t> (item); dbnode <t> N = new dbnode <t> (); If (he AD = NULL) {head = D; return;} n = head; while (N. Next! = NULL) {n = n. next;} n. next = D; D. prev = N;} // The Public void insertbefore (T item, int I) {If (isempty () | I <0) {console. writeline ("list is empty or position is error! "); Return;} // insert if (I = 0) {dbnode <t> q = new dbnode <t> (item); q. next = head; // change "Header" to the second element head. prev = Q; head = Q; // set yourself to "Header" return;} dbnode <t> N = head; dbnode <t> d = new dbnode <t> (); Int J = 0; // locate the previous Element D while (N. next! = NULL & J <I) {d = N; n = n. next; j ++;} If (N. next = NULL) // It indicates to insert (append) {dbnode <t> q = new dbnode <t> (item); N. next = Q; q. prev = N; q. next = NULL;} else {If (j = I) {dbnode <t> q = new dbnode <t> (item); D. next = Q; q. prev = D; q. next = N; N. prev = Q ;}}} /// <summary> /// Insert the element item after position I /// </Summary> /// <Param name = "item"> </param> // /<Param name = "I"> </param> Public void insertafte R (t item, int I) {If (isempty () | I <0) {console. writeline ("list is empty or position is error! "); Return;} if (I = 0) {dbnode <t> q = new dbnode <t> (item); q. next = head. next; head. next. prev = Q; head. next = Q; q. prev = head; return;} dbnode <t> P = head; Int J = 0; while (P! = NULL & J <I) {P = P. next; j ++;} If (j = I) {dbnode <t> q = new dbnode <t> (item); q. next = P. next; If (P. next! = NULL) {P. Next. Prev = Q;} p. Next = Q; q. Prev = P;} else {console. writeline ("position is error! ");}} /// <Summary> /// Delete the element of location I /// </Summary> /// <Param name = "I"> </param> // <returns> </returns> Public t removeat (int I) {If (isempty () | I <0) {console. writeline ("link is empty or position is error! "); Return default (t);} dbnode <t> q = new dbnode <t> (); if (I = 0) {q = head; head = head. next; head. prev = NULL; return Q. data;} dbnode <t> P = head; Int J = 0; while (P. next! = NULL & J <I) {J ++; q = P; P = P. next;} If (j = I) {P. next. prev = Q; q. next = P. next; return p. data;} else {console. writeline ("the node is not exist! "); Return default (t );}} /// <summary> /// obtain the element at the specified position /// </Summary> /// <Param name = "I"> </param> // <returns> </returns> Public t getitemat (int I) {If (isempty () {console. writeline ("list is empty! "); Return default (t);} dbnode <t> P = new dbnode <t> (); P = head; if (I = 0) {return p. data;} Int J = 0; while (P. next! = NULL & J <I) {J ++; P = P. next;} If (j = I) {return p. data;} else {console. writeline ("the node is not exist! "); Return default (t) ;}// search for the index public int indexof (T value) {If (isempty () {console. writeline ("list is empty! "); Return-1;} dbnode <t> P = new dbnode <t> (); P = head; int I = 0; while (! P. Data. Equals (value) & P. Next! = NULL) {P = P. next; I ++;} return I;} // <summary> // element inversion // </Summary> Public void reverse () {dblinklist <t> result = new dblinklist <t> (); dbnode <t> T = This. head; result. head = new dbnode <t> (T. data); t = T. next; // (traverse the elements of the current link from the head and insert them to another empty linked list one by one. In this way, the element sequence of the new linked list is opposite to that of the original linked list) while (T! = NULL) {result. insertbefore (T. data, 0); t = T. next;} This. head = result. head; // directly mount the original linked list to the inverted linked list; Result = NULL; // explicitly clear the reference of the original linked list, so that GC can directly recycle} // get a specified node (for the following test to traverse from the back to the front) Private dbnode <t> getnodeat (int I) {If (isempty ()) {console. writeline ("list is empty! "); Return NULL;} dbnode <t> P = new dbnode <t> (); P = head; if (I = 0) {return P ;} int J = 0; while (P. next! = NULL & J <I) {J ++; P = P. next;} If (j = I) {return P;} else {console. writeline ("the node is not exist! "); Return NULL ;}} /// <summary> /// the prev attribute for testing starts to traverse from the back. /// </Summary> /// <returns> </returns> Public String testprevergodic () {dbnode <t> tail = getnodeat (count ()-1); stringbuilder sb = new stringbuilder (); sb. append (tail. data. tostring () + ","); While (tail. prev! = NULL) {sb. append (tail. prev. data. tostring () + ","); tail = tail. prev;} return sb. tostring (). trimend (',');} public override string tostring () {stringbuilder sb = new stringbuilder (); dbnode <t> N = This. head; sb. append (N. data. tostring () + ","); While (N. next! = NULL) {sb. append (N. next. data. tostring () + ","); n = n. next;} return sb. tostring (). trimend (',');}}}

Test code snippet:

Console. writeline ("-----------------------------------"); console. writeline ("double-stranded table test starts... "); dblinklist <string> dblink = new dblinklist <string> (); dblink. head = new dbnode <string> ("X"); dblink. insertbefore ("W", 0); dblink. insertbefore ("V", 0); dblink. append ("Y"); dblink. insertbefore ("Z", dblink. count (); console. writeline (dblink. count (); // 5 console. writeline (dblink. tostring (); // V, W, X, Y, Z console. Writeline (dblink [1]); // W console. writeline (dblink [0]); // v console. writeline (dblink [4]); // Z console. writeline (dblink. indexof ("Z"); // 4 console. writeline (dblink. removeat (2); // X console. writeline (dblink. tostring (); // V, W, Y, Z dblink. insertbefore ("X", 2); console. writeline (dblink. tostring (); // V, W, X, Y, Z console. writeline (dblink. getitemat (2); // X dblink. reverse (); console. writeline (dblink. tostring ());/ /Z, Y, X, W, V dblink. insertafter ("1", 0); dblink. insertafter ("2", 1); dblink. insertafter ("6", 5); dblink. insertafter ("8", 7); dblink. insertafter ("A", 10); // position is error! Console. writeline (dblink. tostring (); // Z, 1, 2, Y, X, W, 6, V, 8 string _ tail = dblink. getitemat (dblink. count ()-1); console. writeline (_ tail); console. writeline (dblink. testprevergodic (); // 8 console. readkey (); // 8, V, 6, W, X, Y, 2, 1, Z

Of course, from the test code above, it seems that the advantages of the double-chain table are not obvious. The advantage of the double-chain table is that if you need to get its front-end node through a node in the linked list, the double-linked table can be directly found using the prev attribute. To do this, the single-linked table must be searched one by one from the head node one by one using next, so that the time complexity starts from O (N) to O (1), it is obviously more efficient.

 

Note: If you rebuild the double-stranded table and connect the header and tail, that is, the prev attribute of the head points to the last node (it is called tail ), at the same time, pointing the next attribute of the tail node to the head node forms the so-called "circular two-way linked list"

Of course, this structure can add a tail node attribute in the linked list. when inserting or deleting elements, the tail node can be updated cyclically to the end (of course, this will bring some additional overhead to the insert/delete elements), but it can bring room for optimization to the getitemat (int I) method, for example, when the element to be searched is in the first half segment, you can use next to find the element from the head. Otherwise, if the element to be searched is in the second half, you can use the prev attribute to forward the tail node.

 

Note :. net, Microsoft has provided a built-in two-way linked list system. collections. generic. into list <t>. After understanding the principles of double-stranded tables, we recommend that you directly system the built-in linked list.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.