双向链表其实是单链表的改进。 当我们对单链表进行操作时,有时你要对某个结点的直接前驱进行操作时,又必须从表头开始查找。这是由单链表结点的结构所限制的。因为单链表每个结点只有一个存储直接后继结点地址的链域,那么能不能定义一个既有存储直接后继结点地址的链域,又有存储直接前驱结点地址的链域的这样一个双链域结点结构呢?这就是双向链表。
在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点地址,一般称之为右链域;一个存储直接前驱结点地址,一般称之为左链域。
在c语言中双向链表结点类型可以定义为:
typedef struct Node { int item; struct Node *pre; struct Node *next; }DListNode,*DList;
下面的代码就是对双向链表的创建和相关操作:
/*************************************************************************** *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(); }
运行: