http://blog.csdn.net/jw903/article/details/38947753
? ?雙向鏈表其實是單鏈表的改進。 當我們對單鏈表進行操作時,有時你要對某個結點的直接前驅進行操作時,又必須從表頭開始查找。這是由單鏈表結點的結構所限制的。因為單鏈表每個結點只有一個存儲直接后繼結點地址的鏈域,那么能不能定義一個既有存儲直接后繼結點地址的鏈域,又有存儲直接前驅結點地址的鏈域的這樣一個雙鏈域結點結構呢?這就是雙向鏈表。
?? 在雙向鏈表中,結點除含有數據域外,還有兩個鏈域,一個存儲直接后繼結點地址,一般稱之為右鏈域;一個存儲直接前驅結點地址,一般稱之為左鏈域。
?? 在c語言中雙向鏈表結點類型可以定義為:
[cpp]?view plain?copy
- typedef?struct?Node??
- {??
- ????int?item;??
- ????struct?Node?*pre;??
- ????struct?Node?*next;??
- }DListNode,*DList;??
下面的代碼就是對雙向鏈表的創建和相關操作:
[cpp]?view plain?copy
- /***************************************************************************?
- ?*name:jae?chia????????????????????????????????????????????????????????????*?
- ?*date:2014.8.29???????????????????????????????????????????????????????????*?
- ?*version:?1.0?????????????????????????????????????????????????????????????*?
- ?**************************************************************************/??
- #include<iostream>??
- #include<cassert>??
- using?namespace?std;??
- ??
- //雙向鏈表的建立與操作??
- typedef?struct?Node??
- {??
- ????int?item;??
- ????struct?Node?*pre;??
- ????struct?Node?*next;??
- }DListNode,*DList;??
- DList?InsertNodeToTail(DList?head,int?data)//將節點插入到雙向鏈表的尾部??
- {??
- ????if(head==NULL)??
- ????{??
- ????????head=(DList)malloc(sizeof(DListNode));??
- ????????assert(head!=NULL);??
- ????????head->item=data;??
- ????????head->next=NULL;??
- ????????head->pre=NULL;??
- ????}??
- ????else??
- ????{??
- ????????DListNode?*newnode=(DList)malloc(sizeof(DListNode));//創建新的鏈表節點??
- ????????assert(newnode!=NULL);??
- ????????newnode->item=data;??
- ????????newnode->next=NULL;??
- ????????newnode->pre=NULL;??
- ??
- ????????DListNode?*p=head;??
- ????????while(p->next!=NULL)??
- ????????{??
- ????????????p=p->next;??
- ????????}??
- ????????p->next=newnode;??
- ????????newnode->pre=p;??
- ????}??
- ????return?head;??
- }??
- ??
- DList?InsertDListByOrder(DList?head,int?data)//這里的插入操作是按序插入(保證雙向鏈表中的節點以遞增有序)??
- {??
- ????DListNode?*newnode=(DList)malloc(sizeof(DListNode));??
- ????assert(newnode);??
- ????newnode->item=data;??
- ????//newnode->next=NULL;??
- ????//newnode->pre=NULL;??
- ??
- ????DListNode?*p=head;??
- ????DListNode?*prenode;??
- ????for(;p!=NULL;p=p->next)??
- ????{?????
- ????????prenode=p;??
- ????????if(newnode->item?<=p->item)??
- ????????????break;???????
- ????}??
- ????if(p==NULL)//如果遍歷整個鏈表,結點的值都比要插入的小,那么只能在尾端插入??
- ????{??
- ????????prenode->next=newnode;??
- ????????newnode->pre=prenode;??
- ????????newnode->next=NULL;??
- ????}??
- ????else?if(p==head)//如果鏈表中的數都比要插入的數大則在頭部插入;??
- ????{??
- ????????newnode->pre=NULL;??
- ????????newnode->next=head;??
- ????????head=newnode;??
- ????}??
- ????else???//在中間插入??
- ????{??
- ????????p->pre->next=newnode;??
- ????????newnode->pre=p->pre;??
- ??
- ????????newnode->next=p;??
- ????????p->pre=newnode;??
- ????}??
- ????return?head;??
- }??
- ??
- bool?FindNode(DList?head,int?data)//查找鏈表中含有某元素的節點是否存在??
- {??
- ????if(head==NULL)??
- ????{??
- ????????cout<<"the?Dlist?is?NULL"<<endl;??
- ????????return?false;??
- ????}??
- ????DListNode?*p=head;??
- ????while(p!=NULL)??
- ????{??
- ????????if(p->item==data)??
- ????????????return?true;??
- ????????p=p->next;??
- ????}??
- ????return?false;??
- }??
- ??
- DList?DeleteNode(DList?head,int?data)//刪除節點??
- {??
- ????DListNode?*p=head;??
- ????while(p!=NULL)??
- ????{??
- ????????if(p->item==data)??
- ????????????break;??
- ????????p=p->next;??
- ??????????
- ????}??
- ????if(p==NULL)??
- ????{??
- ????????cout<<"the?node?with?data?is?not?existed?in?the?List"<<endl;??
- ????????exit(0);??
- ????}??
- ????if(p==head)//要刪除的結點恰好是雙向鏈表的頭結點??
- ????{??
- ????????DListNode?*tmp=head;??
- ????????head=head->next;??
- ????????head->pre=NULL;//---------------------------------------------------??
- ????????free(tmp);??
- ????}??
- ????else?if(p->next==NULL)//如果要刪除的節點是鏈表的最后一個節點??
- ????{??
- ????????p->pre->next=NULL;??
- ????????free(p);??
- ????}??
- ????else?//刪除中間節點??
- ????{??
- ????????p->pre->next=p->next;??
- ????????p->next->pre=p->pre;??
- ????}??
- ????return?head;????
- }??
- void?PrintDList(DList?head)//打印??
- {??
- ????cout<<"現在,鏈表如下:"<<endl;??
- ????if(head==NULL)??
- ????{??
- ????????cout<<"the?Dlist?is?NULL"<<endl;??
- ????????return?;??
- ????}??
- ????DListNode?*p=head;??
- ????while(p!=NULL)??
- ????{??
- ????????cout<<p->item<<"?";??
- ????????p=p->next;??
- ????}??
- ????cout<<endl<<endl;??
- }??
- void?DestroyDList(DList?head)//銷毀雙向鏈表??
- {??
- ????DListNode?*p=head;??
- ????while(p!=NULL)??
- ????{??
- ????????DListNode?*tmp=p;??
- ????????p=p->next;??
- ????????free(tmp);??
- ????}??
- }??
- ??
- void?Test()??
- {??
- ????DListNode?*head=NULL;??
- ??
- ????for(int?i=0;i<10;i++)???/*利用尾部插入來構造雙向鏈表*/??
- ????????head=InsertNodeToTail(head,i);??
- ????PrintDList(head);??
- ??????
- ????int?a;??
- ????cout<<"輸入要查找的結點的值"<<endl;??
- ????cin>>a;??
- ????if(FindNode(head,a))??
- ????????cout<<"結點存在!"<<endl<<endl;??
- ????else??
- ????????cout<<"結點不存在!"<<endl<<endl;??
- ??
- ????cout<<"刪除結點4..."<<endl;????/*刪除指定節點*/??
- ????head=DeleteNode(head,4);??
- ????PrintDList(head);??
- ??
- ????cout<<"插入結點4..."<<endl;?????/*按序插入*/??
- ????head=InsertDListByOrder(head,4);??
- ????PrintDList(head);??
- ??????
- ????cout<<"刪除頭結點..."<<endl;????/*刪除指定節點*/??
- ????head=DeleteNode(head,0);??
- ????PrintDList(head);??
- ??????
- ????cout<<"刪除尾結點..."<<endl;??
- ????head=DeleteNode(head,9);??
- ????PrintDList(head);??
- ??????
- ????cout<<"插入頭結點..."<<endl;?????/*按序插入*/??
- ????head=InsertDListByOrder(head,0);??
- ????PrintDList(head);??
- ??????
- ????cout<<"插入尾結點..."<<endl;?????/*按序插入*/??
- ????head=InsertDListByOrder(head,10);??
- ????PrintDList(head);??
- ??
- ????DestroyDList(head);??
- }??
- int?main(void)??
- {??
- ????Test();??
- }??
運行: