双链表即双向链表,链表中每个节点有两个指针,分别指向节点的直接前驱和直接后躯。
特点:从双链表的任一节点开始,都可以非常方便的访问他的前驱节点和后继节点。这也是单链表的缺点,单链表可以方便的访问某一节点的后继节点,但没法访问他的前驱节点。
双链表的定义及其操作于单链表类似,要注意的就是每个节点的两个指针域。直接上代码
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<malloc.h> 4 5 //定义双链表 6 typedef struct dnode{ 7 char data; 8 struct dnode *prior; 9 struct dnode *next; 10 }dulinkList; 11 12 //创建双链表:创建链表list 13 void dulinkListCreate(dulinkList **list) 14 { 15 dulinkList *p,*q; 16 *list=(dulinkList*)malloc(sizeof(dulinkList)); 17 (*list)->data='\0'; 18 (*list)->prior=NULL; 19 (*list)->next=NULL; 20 p=*list;//将头节点地址给p 21 char ch; 22 printf("input element:"); 23 while((ch=getchar())!='\n') 24 { 25 q=(dulinkList*)malloc(sizeof(dulinkList)); 26 q->data=ch; 27 q->prior=p; 28 q->next=NULL; 29 p->next=q; 30 p=q; 31 } 32 } 33 34 //查找:根据位置查找节点,查找位置为n处的节点并返回 35 dulinkList * ElemLocatebyNum(dulinkList *list,int n) 36 { 37 dulinkList *p; 38 p=list->next;//第一个节点 39 int i=1;//从1开始是因为链表头的下一个节点才是链表第一个节点 40 while(p && i<n) 41 { 42 p=p->next; 43 i++; 44 } 45 if(p==NULL || i>n) 46 { 47 printf("find error!\n"); 48 return NULL; 49 } 50 return p; 51 } 52 53 //查找:根据数据元素查找,查找数据元素为ch的结点并返回 54 dulinkList * ElemLocatebyVal(dulinkList *list,char ch) 55 { 56 dulinkList *p; 57 p=list->next;//第一个节点 58 while(p && p->data!=ch) 59 { 60 p=p->next; 61 } 62 if(p==NULL) 63 { 64 printf("find error!\n"); 65 return NULL; 66 } 67 return p; 68 } 69 70 //插入结点:在链表list位置n处插入元素ch 71 void dulinkListInsert(dulinkList *list,int n,char ch) 72 { 73 dulinkList *p;//链表位置n处的结点 74 dulinkList *q;//新的结点,内有元素ch 75 //查找节点p 76 p=ElemLocatebyNum(list,n); 77 if(p==NULL) 78 { 79 printf("insert error!\n"); 80 return; 81 } 82 q=(dulinkList*)malloc(sizeof(dulinkList)); 83 q->data=ch; 84 q->prior=p->prior;//指出q的直接前驱 85 p->prior->next=q;//指出q的直接前驱的直接后继 86 q->next=p;//指出q的直接后继 87 p->prior=q;//指出p的直接前驱 88 } 89 90 //删除节点:删除链表list位置n处的节点 91 void dulinkListDelete(dulinkList *list,int n) 92 { 93 dulinkList *p,*q; 94 p=ElemLocatebyNum(list,n);//查找链表位置为n处的节点p 95 q=p->prior; 96 if(p==NULL || q==NULL) 97 { 98 printf("delete error!\n"); 99 return; 100 } 101 q->next=p->next; 102 p->next->prior=q; 103 free(p); 104 } 105 106 int main() 107 { 108 //创建链表 109 dulinkList *list,*p; 110 dulinkListCreate(&list); 111 p=list->next; 112 if(p==NULL) 113 { 114 printf("no element\n"); 115 return 0; 116 } 117 printf("list elment:\n"); 118 while(p) 119 { 120 printf("%c ",p->data); 121 p=p->next; 122 } 123 printf("\n"); 124 //查找:按位置 125 p=ElemLocatebyNum(list,5); 126 printf("position 5 element:%c\n",p->data); 127 //查找:按数据元素 128 p=ElemLocatebyVal(list,'f'); 129 printf("f element:%c\n",p->data); 130 //插入节点 131 dulinkListInsert(list,6,'Q'); 132 p=list->next; 133 if(p==NULL) 134 { 135 printf("no element\n"); 136 return 0; 137 } 138 printf("list elment:\n"); 139 while(p) 140 { 141 printf("%c ",p->data); 142 p=p->next; 143 } 144 printf("\n"); 145 //删除节点 146 dulinkListDelete(list,8); 147 p=list->next; 148 if(p==NULL) 149 { 150 printf("no element\n"); 151 return 0; 152 } 153 printf("list elment:\n"); 154 while(p) 155 { 156 printf("%c ",p->data); 157 p=p->next; 158 } 159 printf("\n"); 160 //释放链表的内存空间 161 p=list; 162 while(p) 163 { 164 list=p; 165 p=list->next; 166 free(list); 167 } 168 169 return 0; 170 }
注意:这段代码严格来说是有问题的,没有在添加和删除节点时没有考虑尾结点的情况,这里为了叙述方便,没有对此进行判断。
1.创建节点
2.查找:根据位置和数据元素查找
3.添加节点:添加时注意逻辑顺序,添加后的节点如下所示,在g和h之间添加Q:
4.删除节点:最后要记得将删除的节点的内存地址释放掉。删除后的节点如下,删除掉了h和k之间的j: