单链表学习 :参考《大话数据结构》
由于自学C语言,本身对于指针、函数、结构体的学习就过于马虎,因此在自学数据结构的时候遇到了不少问题,但随着慢慢地钻研和不断的练习,也找到了一些窍门。单链表就是我遇到的第一个“拦路虎”。
单链表我将它比作一条蛇,而你就像个瞎子。在寻找它的时候,你必须先找到它的头部,然后顺着它的身子一步步的摸索下去,你才能看清它的全身,弄清它(单链表)的原理。
接下来直接介绍单链表的基本操作
以下内容均转自《博客园》——敢光——《数据结构:单链表的基本操作》;自己根据需要和所学进行略微的改动。这里写链接内容
- int initList(linkList *); //初始化一个单链表,具有头指针,头结点,头结点->next=NULL;
int createListHead(linkList *, int n); //头插法创建一个链表,链表长度为n;
int createListTail(linkList *, int n); //尾插法创建一个链表,链表长度为n;
int getlength(linkList *); //获取单链表的长度;
int printList(linkList *); //打印整个链表;
int getElem(linkList ,int i,ElemType ); //获取链表中第i个位置处节点的数据元素;
int insertList(linkList *, int i, ElemType data); //在链表的指定位置(i节点)插入一个节点,i的范围为1~length(链表总长度);
int insertListTail(linkList *, ElemType data); //给链表追加一个节点,在最末尾处增加;
int deleteList(linkList *, int i, ElemType *data); //删除指定位置(i节点)处的节点,i的范围为1~length(链表总长度);
int clearList(linkList *); //删除整个链表,使头结点->next=NULL;
(一)ADT:**
1 typedef int ElemType;
2 typedef struct Node {
3 ElemType data;
4 struct Node * next;
5 }Node;
6 typedef struct Node* linkList;
**(
二)初始化*:int initList(linkList *L)
1 int initList(linkList *L)
2 {
3 (*L) = (linkList)malloc(sizeof(Node));
4 (*L)->next = NULL;
5 printf("链表初始化成功\n");
6 return 1;
7 }
初始化一个指向头节点的指针,使头指针->next=NULL,头指针->data不做处理;
(三)创建一个单链表
1 int createListHead(linkList *L,int n) {
2 linkList p;
3 int i = 0;
4 srand((int)time(0));
5 for (i = 0; i < n; i++)
6 {
7 p= (linkList)malloc(sizeof(Node));
8 p->data = rand() % 100;
9 printf("testing:Node[%d]=%d\n",i+1,p->data);
10 p->next = (*L)->next;
11 (*L)->next = p;
12 }
13 printf("链表(头插法)创建成功\n");
14 return 1;
15 }
int createListTail(linkList *L, int n) {
linkList p, temp;
temp = (*L);
int i;
srand((int)time(0));
for (i = 0; i < n;i++) {
p = (linkList)malloc(sizeof(Node));
p->data = rand() % 100;
printf("testing:Node[%d]=%d\n", i + 1, p->data);
p->next = NULL;
temp->next = p;
temp = p;
}
printf("链表(尾插法)创建成功\n");
return 1;
}
(四)获取链表的长度
1 int getlength(linkList *L) {
2 linkList p;
3 int length=0;
4 p = (*L)->next;//p指向第一个节点;
5 while (p) {
6 length++;
7 p = p->next;
8 }
9 return length;
10 }
*
(五)打印整个链表*
1 int printList(linkList *L) {
2 linkList p;
3 int i = 0;
4 p = (*L)->next;//p指向第一个节点;
5 printf("-----------打印整个链表-----------\n");
6 if (p==NULL) {
7 printf("这是一个空链表.\n");
8 }
9 while (p) {
10 i++;
11 printf("第%d个节点的数据data为=%d\n",i,p->data);
12 p = p->next;
13 }
14 return 1;
15 }
(六)获取指定位置处的节点元素**;
1 int getElem(linkList *L, int i, ElemType *getdata) {
2 linkList p;
3 p = (*L)->next;
4 int j = 1;
5 while (p&&j<i) {
6 j++;
7 p = p->next;
8 }
9 if (!p||j>i)
10 {
11
12 *getdata = -1;
13 return 0;
14 }
15 *getdata = p->data;
16 printf("查询成功!\n", i);
17 return 1;
18 }
(七)插入节点;
插入节点分为两种,一种是在链表的长度范围内插入节点,第二种是在链表的尾部追加一个节点;
假设链表的长度为10,第一种可以在1-10位置处插入节点,比如在第10个位置插入一个节点,则原先的第10节点变为了11节点,但是第二种是所有节点位置都不变,在第11个位置追加一个新的节点;
1 int insertList(linkList *L, int i, ElemType data)
2 {
3 linkList p;
4 linkList insNode;
5 p = (*L);
6 int j=0;
7 // 链表为空,在第1个位置插入一个新的节点;
8 if (p ->next == NULL) {
9 printf("链表为空,默认在第一个位置插入一个节点.\n");
10 insNode = (linkList)malloc(sizeof(Node));
11 insNode->data = data;
12 insNode->next = p->next;
13 p->next = insNode;
14 printf("节点插入成功.\n");
15 return 1;
16 }
17 // 链表非空的情况下,可以在i=1~length的位置插入节点,如果超过了链表的长度,就会提示错误;
18 // 其实如果在length+1的位置处插入一个新节点,就相当于在尾部追加一个节点,在本函数中会报错,可以单独实现一个函数;
19 while(p && j<i-1)
20 {
21 j++;
22 p = p->next;
23 //printf("j=%d\tp->data=%d\n", j, p->data);
24 }
25 if (p->next==NULL) {
26 printf("您要插入的位置,超过了链表的长度 %d,请重新操作!\n",j);
27 return 0;
28 }
29 insNode = (linkList)malloc(sizeof(Node));
30 insNode->data = data;
31 insNode->next = p->next;
32 p->next = insNode;
33
34 printf("节点插入成功\n");
35 return 1;
36 }
追加节点;
1 int insertListTail(linkList *L, ElemType data)
2 {
3 linkList temp;
4 linkList p=(*L);
5 while(p) {
6 temp = p;
7 p = p->next;
8 }
9 p = (linkList)malloc(sizeof(Node));
10 p->data = data;
11 p->next = NULL;
12 temp->next = p;
13 printf("节点插入成功\n");
14 return 1;
15 }
(八)删除节点;
1 int deleteList(linkList *L, int i, ElemType *data)
2 {
3 linkList p,pnext;
4 int j = 0;
5 p = (*L);
6 if (p->next == NULL) {
7 printf("链表为空,无法删除指定节点.\n");
8 *data = -1;
9 return 0;
10 }
11 while (p->next && j<i-1) {
12 j++;
13 p = p->next;
14 //printf("j=%d\t p->data=%d\n",j,p->data);
15 }//条件最多定位到最后一个节点;
16 if ( p->next == NULL) {
17 printf("您要删除的节点,超过了链表的长度 %d,请重新操作!\n", j);
18 *data = -1;
19 return 0;
20 }
21 pnext = p->next;
22 p->next = pnext->next;
23 *data = pnext->data;
24 free(pnext);
25 printf("节点删除成功\n");
26 return 1;
27 }
(九)删除这个链表;
1 int clearList(linkList *L) {
2 linkList p, temp;
3 p = (*L)->next;//p指向第一个节点
4 while (p) {
5 temp = p;
6 p = p->next;
7 free(temp);
8 }
9 (*L)->next = NULL;
10 printf("整个链表已经clear.\n");
11 return 1;
12 }