一.单向链表:

由于线性表的顺序存储结构(数组),在插入和删除需要移动大量元素以及其他特殊情况下,效率低下,耗时费力,此处引入了链表的概念。

链表的基本组成单元为结点(node),包括两个域:存储数据元素信息的域->数据域;存储直接后继存储位置的域(指针)->指针域。

 

数据结构学习笔记01链表

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <time.h>
  4 #define OK 1
  5 #define ERROR 0
  6 
  7 
  8 typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
  9 typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */
 10 
 11 typedef struct Node
 12 {
 13     ElemType data;
 14     struct Node *next;
 15 }Node;
 16 typedef struct Node *LinkList; //定义LinkList
 17 
 18 Status InitList(LinkList *L);
 19 Status Destroy(LinkList L);
 20 Status ClearList(LinkList *L);
 21 bool ListEmpty(LinkList L); 
 22 int ListLength(LinkList L);
 23 Status GetElem(LinkList L,int i,ElemType *e);
 24 int LocateElem(LinkList L,ElemType e);
 25 Status PriorElem(LinkList *L, ElemType cur_e, LinkList *pre_e);
 26 Status NextElem(LinkList *L, ElemType cur_e, LinkList *next_e);
 27 Status ListInsert(LinkList *L,int i,ElemType e);
 28 Status ListDelete(LinkList *L,int i,ElemType *e);
 29 Status ListTraverse(LinkList L);
 30 void CreateListHead(LinkList *L, int n);
 31 void CreateListTail(LinkList *L, int n);
 32 
 33 Status visit(ElemType c)
 34 {
 35     printf("%d ",c);
 36     return OK;
 37 }
 38 
 39 /*初始化顺序线性表: 构造一个空的线性表L*/
 40 Status InitList(LinkList *L) 
 41 { 
 42     *L = (LinkList)malloc(sizeof(Node)); /* 产生头结点,并使L指向此头结点,L为头指针 */
 43     if(!(*L)) /* 存储分配失败 */
 44             return ERROR;
 45     (*L)->next = NULL; /* 指针域为空 */
 46 
 47     return OK;
 48 }
 49 /*初始条件:线性表L已存在。操作结果:销毁线性表L*/
 50 Status Destroy(LinkList L)
 51 {
 52     ClearList(&L);
 53     free(L);
 54     L = NULL;
 55 }
 56 
 57 /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
 58 Status ClearList(LinkList *L)
 59 { 
 60     LinkList p,q;
 61     p=(*L)->next;           /*  p指向第一个结点 */
 62     while(p)                /*  没到表尾 */
 63     {
 64         q=p->next;
 65         free(p);
 66         p=q;
 67     }
 68     (*L)->next = NULL;        /* 头结点指针域为空 */
 69     return OK;
 70 }
 71 
 72 /* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
 73 bool ListEmpty(LinkList L)
 74 { 
 75     if(L->next)
 76         return false;
 77     else
 78         return true;
 79 }
 80 
 81 /* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
 82 int ListLength(LinkList L)
 83 {
 84     int i = 0;
 85     LinkList p=L->next; /* p指向第一个结点 */
 86     while(p)                        
 87     {
 88         i++;
 89         p=p->next;
 90     }
 91     return i;
 92 }
 93 
 94 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) 
 95 操作结果:用e返回L中第i个数据元素的值 */
 96 Status GetElem(LinkList L,int i,ElemType *e)
 97 {
 98     int j = 1;             /* j为计数器 */
 99     LinkList p;             /* 声明一结点p */
100     p = L->next;         /* 让p指向链表L的第一个结点 */          
101     while (p && j < i) {   /* p不为空或者计数器j还没有等于i时,循环继续 */  
102         p = p->next;       /* 让p指向下一个结点 */
103         j++;
104     }
105     if ( !p || j>i ) 
106         return ERROR;       /*  第i个元素不存在 */
107     *e = p->data;        /*取第i个元素的数据 */
108     return OK;
109 }
110 
111 /* 初始条件:顺序线性表L已存在 
112 操作结果:返回L中第1个与e满足关系的数据元素的位序。
113 若这样的数据元素不存在,则返回值为0 */
114 int LocateElem(LinkList L,ElemType e)
115 {
116     int i=0;
117     LinkList p=L->next;
118     while(p)
119     {
120         i++;
121         if(p->data==e) /* 找到这样的数据元素 */
122                 return i;
123         p=p->next;
124     }
125 
126     return 0;
127 }
128 
129 /*初始条件:线性表L已存在
130 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,
131 否则操作失败,pre_e无定义*/
132 Status PriorElem(LinkList *L, ElemType cur_e, LinkList *pre_e)
133 {
134     LinkList p;
135     p = (*L)->next;
136     if(p->data == cur_e) {        /* 是第一个 */
137         pre_e = NULL;
138         return ERROR;
139     }
140     while(p->next)
141     {
142         if(p->next->data == cur_e) {
143             *pre_e = p;
144             return OK;
145         }
146         p = p->next;
147     }
148     pre_e = NULL;
149     return ERROR;
150 }
151 
152 /*初始条件:线性表L已存在
153 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后驱,
154 否则操作失败,next_e无定义*/
155 Status NextElem(LinkList *L, ElemType cur_e, LinkList *next_e)
156 {
157     LinkList p;
158     p = (*L);
159     while(p->next) 
160     {
161         if(p->data == cur_e) {
162             *next_e = p->next;
163             return OK;
164         }
165         p = p->next;
166     } 
167     *next_e = NULL;
168     return ERROR;
169 }
170 
171 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) + 1,
172 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
173 Status ListInsert(LinkList *L,int i,ElemType e)
174 { 
175     int j = 1;
176     LinkList p,s;
177     p = *L;  
178     while (p && j < i) {    /* 寻找第i个结点 */
179         p = p->next;
180         ++j;
181     } 
182     if (!p || j > i) 
183         return ERROR;   /* 第i个元素不存在 */
184     s = (LinkList)malloc(sizeof(Node));  /*  生成新结点(C语言标准函数) */
185     s->data = e;  
186     s->next = p->next;      /* 将p的后继结点赋值给s的后继  */
187     p->next = s;          /* 将s赋值给p的后继 */
188     return OK;
189 }
190 
191 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)
192 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
193 Status ListDelete(LinkList *L,int i,ElemType *e) 
194 { 
195     int j;
196     LinkList p,q;
197     p = *L;
198     j = 1;
199     while (p->next && j < i) {    /* 遍历寻找第i个元素 */
200         p = p->next;
201         ++j;
202     }
203     if (!(p->next) || j > i) 
204         return ERROR;           /* 第i个元素不存在 */
205     q = p->next;
206     p->next = q->next;            /* 将q的后继赋值给p的后继 */
207     *e = q->data;               /* 将q结点中的数据给e */
208     free(q);                    /* 让系统回收此结点,释放内存 */
209     return OK;
210 }
211 
212 /* 初始条件:顺序线性表L已存在
213 操作结果:依次对L的每个数据元素输出 */
214 Status ListTraverse(LinkList L)
215 {
216     LinkList p=L->next;
217     while(p)
218     {
219         visit(p->data);
220         p=p->next;
221     }
222     printf("\n");
223     return OK;
224 }
225 
226 /*  随机产生n个元素的值,建立带表头结点的单链线性表L(头插法) */
227 void CreateListHead(LinkList *L, int n) 
228 {
229     LinkList p;
230     int i;
231     srand(time(0));                         /* 初始化随机数种子 */
232     *L = (LinkList)malloc(sizeof(Node));
233     (*L)->next = NULL;                      /*  先建立一个带头结点的单链表 */
234     for (i=0; i<n; i++) 
235     {
236         p = (LinkList)malloc(sizeof(Node)); /*  生成新结点 */
237         p->data = rand()%100+1;             /*  随机生成100以内的数字 */
238         p->next = (*L)->next;    
239         (*L)->next = p;                        /*  插入到表头 */
240     }
241 }
242 
243 /*建立带表头结点的单链线性表L(尾插法) */
244 void CreateListTail(LinkList *L, int n) 
245 {
246     LinkList p,r;
247     *L = (LinkList)malloc(sizeof(Node));     /* L为整个线性表 */
248     r = *L;                              /* r为指向尾部的结点 */
249     for (int i = 0; i < n; i++) {
250         p = (Node *)malloc(sizeof(Node));      /*  生成新结点 */
251         scanf("%d",p->data); 
252         r->next = p;        /* 将表尾终端结点的指针指向新结点 */
253         r = p;            /* 将当前的新结点定义为表尾终端结点 */
254     }
255     r->next = NULL;                       /* 表示当前链表结束 */
256 }
257 int main()
258 {
259     LinkList L, pre_e,next_e;    //创建一个可以指向结点的指针 
260     CreateListTail(&L,10);
261     ListInsert(&L,11,55); 
262     ListTraverse(L);
263     PriorElem(&L, 3, &pre_e);
264     NextElem(&L, 3, &next_e);
265     printf("前驱%d\n",(*pre_e).data);
266     printf("后继%d\n",(*next_e).data);
267     Destroy(L);
268 
269         
270     return 0;
271 } 
sj1_0

相关文章: