I read the linked list part of the book "C and pointer" (Chapter 1) in the last two days. I feel that the author has written so well that the C pointer is so beautiful. I have a little bit of experience after reading it. Record it here for future review.
Here we only discuss double-stranded tables (doubly linked list), more specificallyInsertion of ordered double-stranded tables.
A double-stranded table means that each node in the linked list contains two node type pointers, one pointing to the next node and the other pointing to the previous node.
The data structure of linked list nodes is defined as follows:
typedef struct NODE{ struct NODE *fwd;// forward---pointer to the next node in the list struct NODE *bwd;//backward---pointer to the previous node in the list int value;} Node;
As shown in, FWD of the root node points to the first node in the linked list, fwd of the first node points to the second node, and so on. Note that FWD of the last node points to null; the BWD of the last node refers to the previous node, and so on. Note that the bwd of the first node points to null. In addition, note that the BWD of the Root Node also points to the last node.
In this way, we can traverse the nodes of the double-Link Table in two directions, making the linked list operation more convenient and convenient.
For the insertion of an ordered double-stranded table, the first step is to locate the Insertion Location of the new node.
Node *this,*next,*new_node;for(this=root;(next=this->fwd)!=NULL;this=next){ if(next->value==new_value) return 1; if(next->value > new_value) break;}
The above is the code used in the book to find the new node Insertion Location. The program inserts new_node into the center of the node pointed to by this and next, but does not insert the existing value in the linked list.
Insert position analysis for new nodes:
1) Insert the new value to the center of the linked list, as shown in:
The linked list after the new node is inserted is as follows:
Code implementation:
this->fwd=new_node;new_node->fwd=next; next->bwd=new_node;new_node->bwd=this;
When analyzing problems, pay attention to the boundary situation, which is often a special case.
2) Insert a new node at the beginning of the linked list
The linked list after the new node is inserted is as follows:
Code implementation:
this->fwd=new_node;new_node->fwd=next; next->bwd=new_node;new_node->bwd=NULL;
Note that in this case
Root = this;
3) Insert a new node at the end of the linked list
The linked list after the new node is inserted is as follows:
Code implementation:
this->fwd=new_node;new_node->fwd=NULL:new_node->bwd=this; root->bwd=new_node;
Note the following:
In this case, there is next = NULL;
4) another special case is that the original linked list is empty.
The linked list after the new node is inserted is as follows:
Code implementation:
this->fwd=new_node;new_node->fwd=NULL;new_node->bwd=NULL; this->bwd=new_node;
Note the following:
In this case
Next = NULL;
This = root;
Insert the implementation code of the new node
1) implement your own code
/*malloc a new node for the would-be insertion */ new_node=(Node *)malloc(sizeof(Node)); if(!new_node){ printf("malloc new node error!\n"); exit(2); } new_node->value=new_value; if(!this->fwd){//the list is empty before insertion this->fwd=new_node; new_node->fwd=NULL; new_node->bwd=NULL; this->bwd=new_node; } else if(!next->bwd){//insert to the right position after root this->fwd=new_node; new_node->fwd=next; next->bwd=new_node; new_node->bwd=NULL; } else if(!next->fwd){//insert in the end this->fwd=new_node; new_node->fwd=NULL: new_node->bwd=this; root->bwd=new_node; } else{//insert in the middle of list this->fwd=new_node; new_node->fwd=next; next->bwd=new_node; new_node->bwd=this; }
The code I write can also implement the function of inserting new nodes, but it is too redundant.
2) code analysis and implementation in the book
New node insertion position |
Code Implementation |
Notes |
Middle |
1) This-> FWD = new_node; 2) new_node-> FWD = next; 3) Next-> BWD = new_node; 4) new_node-> BWD = this; |
|
Start |
1) This-> FWD = new_node; 2) new_node-> FWD = next; 3) Next-> BWD = new_node; 4) new_node-> BWD = NULL; |
Root = this; |
End |
1) This-> FWD = new_node; 2) new_node-> FWD = NULL: 3) new_node-> BWD = this; 4) Root-> BWD = new_node; |
Next = NULL; |
Empty list |
1) This-> FWD = new_node; 2) new_node-> FWD = NULL; 3) new_node-> BWD = NULL; 4) This-> BWD = new_node; |
Next = NULL; This = root; |
Observe this table carefully:
1. In four cases, the first and second lines of code are exactly the same.
For end and empty, note that next is null in notes.
--- This revelation can be used to extract the first and second lines of code from the IF and else statements and put them before the IF and else statements.
2. The fourth line of code in empty and end is the same, that is, this-> BWD = new_node, because this = root in empty;
In the middle and start cases, the third line of code is the same, that is, next-> BWD = new_node;
Here we can find that:
This-> BWD = new_node;
Next-> BWD = new_node;
The difference is that this and next. Therefore, we are looking for a criterion to determine whether a condition is obtained.
This-> BWD = new_node; or next-> BWD = new_node.
Observe the Notes column, for empty, end, next = NULL; for middle, start, next! = NULL,
Therefore, whether next is equal to NULL is a condition.
if(next==NULL) this->bwd=new_node;else next->bwd=new_node;
3. The fourth line of start code is the same as the third line of empty code, that is, new_node-> BWD = NULL;
The code of the fourth line of the middle is the same as that of the third line of the end, that is, new_node-> BWD = This.
Observe the notes to see whether this is equal to root and can be used as the judgment condition.
if(root==this) new_node->bwd=NULL;else new_node->bwd=this;
To sum up, the complete code is as follows:
//the following method is from the book with little change.int dll_insert(Node *root,int new_value){ Node *this,*next,*new_node; for(this=root;(next=this->fwd)!=NULL;this=next){ if(next->value==new_value) return 1; if(next->value > new_value) break; } new_node=(Node *)malloc(sizeof(Node)); if(!new_node){ printf("malloc new node error!\n"); return -1; } new_node->value=new_value; new_node->fwd=next; this->fwd=new_node; if(root==this) new_node->bwd=NULL; else new_node->bwd=this; if(next==NULL) root->bwd=new_node; else next->bwd=new_node; root->value++; return 1; }
I hope I have made it clear and hope I have not used any typos.
Thank you for your criticism!