Romi-知行合一

轻轻的风轻轻的梦,轻轻的晨晨昏昏, 淡淡的云淡淡的泪,淡淡的年年岁岁。
  博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

数据结构学习3——双链表

Posted on 2012-08-28 12:42  romi  阅读(2202)  评论(0编辑  收藏  举报

双链表即双向链表,链表中每个节点有两个指针,分别指向节点的直接前驱和直接后躯。

特点:从双链表的任一节点开始,都可以非常方便的访问他的前驱节点和后继节点。这也是单链表的缺点,单链表可以方便的访问某一节点的后继节点,但没法访问他的前驱节点。

双链表的定义及其操作于单链表类似,要注意的就是每个节点的两个指针域。直接上代码

  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: