1 #include <stdio.h>
2 #include <stdlib.h>
3 typedef struct node
4 {
5 int data;
6 struct node *next;
7 }Node;
//创建一个带头结点的空链表
int createList(Node ** head)
{
*head = (Node*)malloc(sizeof(Node));
if(*head == NULL)
{
return -1;
}
else
{
(*head)->next = NULL;
return 0;
}
}
1 //尾插1 //找前驱节点方式
2 void insertList_end(Node *head,int data)
3 {
4 Node* newNode = (Node*)malloc(sizeof(Node));
5 newNode->data = data;
6
7
8 while(head->next)
9 {
10 head = head->next;
11 }
12
13 head->next = newNode;
14 newNode->next = NULL;
15 }
1 //尾插2
2 //找待插入的空间地址,也就是前驱节点的next成员所在的内存空间
3 //这种方式更适合操作无头节点的链表
4 void insertList_end(Node *head, int data)
5 {
6 Node* newNode = (Node*)malloc(sizeof(Node));
7 newNode->data = data;
8 newNode->next = NULL;
9
10 Node** p = &(head->next);//最符合逻辑的初始化写法
11 // Node** p = &head;
12 while(*p)//遍历到待插入的地址结束。
13 {
14 p = &((*p)->next);
15 }
16 *p = newNode;
17 }
1 //头插1
2 void insertList_head(Node *head,int data)
3 {
4 Node* newNode = (Node*)malloc(sizeof(Node));
5 newNode->data = data;
6
7 newNode->next = head->next;
8 head->next = newNode;
9 }
1 //头插2 //这个方式用在有头链表头插上就有点脱裤子放屁了。但还是写一写好了
2 //这个方式适合用于无头链表的头插
3 void insertList_head(Node *head, int data)
4 {
5 Node* newNode = (Node*)malloc(sizeof(Node));
6 newNode->data = data;
7
8 Node **p = &(head->next);
9 newNode->next = (*p);
10 *p = newNode;
11 }
1 //查找1
2 //功能:返回待查找节点的地址,不存在返回NULL
3 Node* searchList(Node *head,int findData)
4 {
5 #if 1
6 head = head->next;
7 while(head)
8 {
9 if(head->data == findData)
10 {
11 return head;
12 }
13 head = head->next;
14 }
15 return NULL;
16 #endif
17
18 #if 0//只是做了点优化
19 head = head->next;
20 while(head)
21 {
22 if(head->data == findData)
23 {
24 break;
25 }
26 head = head->next;
27 }
28 return head;//因为没找到head会==NULL时结束循环,找到会跳出循环,所以上面两个return可以合为一个
29
30 #endif
31 }
32
33
34
35
36
37
38
39 //删除1 //遍历到前驱节点
40 //功能:已有待删除节点的地址,实现删除此节点的操作
41 void deleteNodeList1(Node* head,Node *deleteNode)
42 {
43 while(head->next != deleteNode)//遍历到前驱节点
44 {
45 head = head->next;
46 }
47 head->next = deleteNode->next;
48 free(deleteNode);
49 }
50
51
52 //删除1.1 //对删除1的优化版,无需遍历。
53 //功能:已有待删除节点的地址,实现删除此节点的操作,优化版
54 //优化的原理是后驱节点的所有数据覆盖拷贝到待删除节点,再删除后驱节点。不需再遍历
55 //但是特殊情况是如果待删除节点为尾节点并没有后驱节点,所以需要分两种情况。
56 void deleteNodeList2(Node* head,Node *deleteNode)
57 {
58 Node* postNode = deleteNode->next;
59 if(postNode)
60 {
61 deleteNode->data = postNode->data;
62 deleteNode->next = postNode->next;
63 free(postNode);
64 }
65 else
66 {
67 while(head->next != deleteNode)//遍历到前驱节点
68 {
69 head = head->next;
70 }
71 head->next = deleteNode->next;
72 free(deleteNode);
73 }
74
75 }
1 //查找2
2 //功能:返回待查找节点的前驱节点的地址。方便后来的操作
3 //注意点,如果不存在待查找节点,那更不存在前驱节点了,直接返回NULL
4 //另外,此方式只适合有头链表,不适合无头链表,因为如果无头链表第一个有效节点没前驱节点。
5 Node* searchListPre(Node *head,int findData)
6 {
7 while(head->next)
8 {
9 if(head->next->data == findData)
10 {
11 return head;
12 }
13 head = head->next;
14 }
15 return NULL;
16 }
17
18
19 //删除2
20 //功能:已有待删除节点的前驱节点的地址,实现删除此待删节点的操作
21 //需配合返回前驱节点的查找函数
22 //只适合有头链表
23 void deleteNodeList3(Node *deleteNodePre)
24 {
25 Node* deleteNode = deleteNodePre->next;
26 deleteNodePre->next = deleteNode->next;
27 free(deleteNode);
28
29 }
1 //查找3
2 //返回待查找节点的所在的挂载空间的地址,(挂载空间里存储的"待查找节点的首地址")(挂载空间也就是前驱节点的next成员所在的空间),如果不存在此节点,返回NULL
3 Node** searchList(Node *head,int findData)
4 {
5 Node **p = &(head->next);
6 while(*p)
7 {
8 if((*p)->data == findData)
9 return p;
10
11 p = &((*p)->next);
12 }
13 return NULL;
14 }
15
16 //删除3
17 void deleteNodeList(Node **deleteNode)
18 {
19 Node* temp = *deleteNode;
20 *deleteNode = (*deleteNode)->next;
21 free(temp);
22 }
1 //逆置链表
2 //方法为拆分为两个链表,一个包含头结点的空链表A,一个是不带头结点的链表B。,
3 //从链表B里从头到尾取节点,用头插法将节点依次插入到链表A中。
4 void reverseList(Node * head)
5 {
6 //无头链表B
7 Node* headB = head->next;
8
9 //有头空链表A
10 head->next = NULL;
11 Node* headA = head;
12
13 while(headB)
14 {
15 Node* newNode = headB;
16 headB = headB->next;
17 newNode->next = headA->next;
18 headA->next = newNode;
19 }
20 }
1 //求链表长度
2 int getLenList(Node* head)
3 {
4 head = head->next;
5 int len = 0;
6 while(head)
7 {
8 len++;
9 head= head->next;
10 }
11 return len;
12 }
1 //清空链表 留头节点释放删除掉所有有效节点,只留头结点
2 void clearList(Node* head)
3 {
4 Node* temp = head->next;
5 head->next = NULL;
6
7 while(temp)
8 {
9 Node* p = temp;
10 // free(p);
11 temp = temp->next;
12 free(p);
13 }
14 }
1 //销毁链表 释放删除掉所有节点,包括头结点
2 //头结点被销毁后,调用函数中头指针应该置为NULL,相当于修改了其指向,因此需要使用二级指针参数。
3 void destroyList(Node** head)
4 {
5 while(*head)//循环结束会为NULL
6 {
7 Node* temp = *head;
8 *head = (*head)->next;
9
10 free(temp);
11 }
12 }
1 //销毁链表 释放删除掉所有节点,包括头结点
2 //头结点被销毁后,调用函数中头指针应该置为NULL,相当于修改了其指向,因此需要使用二级指针参数。
3 void destroyList(Node** head)
4 {
5 while(*head)//循环结束会为NULL
6 {
7 Node* temp = *head;
8 *head = (*head)->next;
9
10 free(temp);
11 }
12 }
1 //对链表排序,使用选择排序
2 /*-------------------使用选择排序--------------------*/
3 //对数据域进行交换1 套用选择排序模板
4 void selectSortDataUp(Node* head)//升序
5 {
6 int i,j;
7 int len = getLenList(head);
8 // printf("len = %d\n",len);
9 Node* cur = head;
10 Node* post = NULL;
11
12
13 for(i = 0;i<len-1;i++)
14 {
15 cur = cur->next;
16 post = cur->next;
17 for(j = i+1;j<len;j++)
18 {
19 if(cur->data > post->data)
20 {
21 #if 0
22 Node temp;
23 temp.data = cur->data;
24 cur->data = post->data;
25 post->data = temp.data;
26 #endif
27 #if 1
28 int temp;
29 temp = cur->data;
30 cur->data = post->data;
31 post->data = temp;
32 #endif
33
34 }
35 post = post->next;
36 }
37 }
38 }
39
40 //对数据域进行交换2 判NULL方式
41 void selectSortDataDown(Node* head)//降序
42 {
43 Node *Nodei,*Nodej;
44 for(Nodei = head->next ; Nodei->next ; Nodei = Nodei->next)
45 {
46 for(Nodej = Nodei->next; Nodej ;Nodej = Nodej->next)
47 {
48 if(Nodei->data < Nodej->data)
49 {
50 int temp = Nodei->data;
51 Nodei->data = Nodej->data;
52 Nodej->data = temp;
53 }
54 }
55 }
56 }
57
58
59 //对数据域进行交换2.1 选择排序的优化,比而不换,只记下标,比完再换。
60 void selectSortDataDown2(Node* head)//降序
61 {
62 Node *Nodei,*Nodej;
63 Node *idx;
64 for(Nodei = head->next ; Nodei->next ; Nodei = Nodei->next)
65 {
66 idx = Nodei;
67 for(Nodej = Nodei->next; Nodej ;Nodej = Nodej->next)
68 {
69 if(idx->data < Nodej->data)
70 {
71 idx = Nodej;
72 }
73 }
74 if(idx != Nodei)
75 {
76 Nodei->data ^= idx->data;
77 idx->data ^= Nodei->data;
78 Nodei->data ^= idx->data;
79 }
80
81 }
82 }
83
84
85 //对指针域进行交换,调整节点在链表结构中的挂载顺序
86 //i,j,iPre,jPre,都是指向一个节点的,打断重连时并没有改其指向,所以重连后,这四个指针仍旧指向原先的节点。
87 //始终保持让i指向左位置,j指向右位置
88 void selectSortPointer(Node* head)//升序
89 {
90 Node* i;
91 Node* j;
92 Node* iPre;
93 Node* jPre;
94 for(iPre = head,i = head->next;i->next;iPre = iPre->next,i = iPre->next)
95 {
96 for(jPre = i,j = jPre->next;j;jPre = jPre->next,j = jPre->next)
97 {
98 if(i->data > j->data)
99 {
100 if(jPre == i)
101 {
102 iPre->next = j;
103 Node* temp = j->next;
104 j->next = i;
105 i->next = temp;
106
107 i = iPre->next;
108 jPre = i;
109 }
110 else
111 {
112 iPre->next = j;
113 Node* temp = j->next;
114 j->next = i->next;
115 jPre->next = i;
116 i->next = temp;
117
118 i = iPre->next;
119 }
120 }
121 }
122 }
123 }
1 //对链表排序,使用选择排序
2 //对数据域进行交换1 套用冒泡排序模板
3 void bubbleSortDataUp(Node* head)//升序
4 {
5 int i,j;
6 int len = getLenList(head);
7 Node* cur = NULL;
8 for(i = 0;i<len-1;i++)
9 {
10 cur = head->next;
11 for(j=0;j<len-1-i;j++)
12 {
13 if(cur->data > cur->next->data)
14 {
15 cur->data ^= cur->next->data;
16 cur->next->data ^= cur->data;
17 cur->data ^= cur->next->data;
18 }
19 cur = cur->next;
20 }
21 }
22 }
23
24
25 //对数据域进行交换1.1 优化版,已序而不排
26 void bubbleSortDataUp2(Node* head)
27 {
28 int i,j;
29 int len = getLenList(head);
30 Node* cur = NULL;
31 int doswap;//
32 for(i = 0;i<len-1;i++)
33 {
34 doswap = 0;//
35 cur = head->next;
36 for(j=0;j<len-1-i;j++)
37 {
38 if(cur->data > cur->next->data)
39 {
40 doswap = 1;//
41
42 cur->data ^= cur->next->data;
43 cur->next->data ^= cur->data;
44 cur->data ^= cur->next->data;
45
46 }
47 cur = cur->next;
48 }
49 if(doswap == 0)//
50 break;
51 }
52 }
53
54 //对数据域进行交换2 判NULL方式没法实现
55
56
57
58 //对指针域排序
59 void bubbleSortPointer(Node* head)//升序
60 {
61 int len = getLenList(head);
62 int m,n;
63 Node *i = head->next;
64 Node *j = i->next;
65 Node *iPre = head;
66 for(m = 0;m<len-1;m++)
67 {
68 for(n = 0;n<len-1-m;n++)
69 {
70 if(i->data > j->data)
71 {
72 iPre->next = j;
73 Node* temp = j->next;
74 j->next = i;
75 i->next = temp;
76
77 i = iPre->next;
78 j = i->next;
79 }
80
81 iPre = iPre->next;
82 i = iPre->next;
83 j = i->next;
84 }
85
86 iPre = head;
87 i = iPre->next;
88 j = i->next;
89 }
90 }
1 //正序打印链表
2 void traverseList(Node* head)
3 {
4 head = head->next;
5 while(head)
6 {
7 printf("%d ",head->data);
8 head = head->next;
9 }
10 }
11
12
13
14 //逆序打印链表
15 void traverseList2(Node* head)
16 {
17 if(head->next == NULL)
18 {
19 return;
20 }
21 else
22 {
23 head = head->next;
24 traverseList2(head);
25 printf("%d ",head->data);
26 }
27 }
1 int main(void) //测试,均通过QT测试通过。
2 {
3 Node * listhead;
4 int res = createList(&listhead);
5 if(res == 0)
6 {
7 printf("create succeed\n");
8 }
9 else
10 {
11 printf("create error\n");
12 exit(-1);
13 }
14 int i;
15 for(i = 0; i<5;i++)
16 {
17 // insertList_end(listhead,i);
18 insertList_head(listhead,i);
19 }
20
21 traverseList(listhead);putchar(10);
22
23 #if 0
24 Node* findNode = searchList(listhead,3);
25 if(findNode)
26 printf("%d\n",findNode->data);
27 else
28 printf("There is no such node\n");
29 #endif
30 #if 0
31 Node* findNodePre = searchListPre(listhead,3);
32 Node* findNode = findNodePre->next;
33 if(findNode)
34 printf("%d\n",findNode->data);
35 else
36 printf("There is no such node\n");
37 #endif
38
39 #if 0
40 Node** findNode = searchList(listhead,3);
41 if(findNode)
42 printf("%d\n",(*findNode)->data);
43 else
44 printf("There is no such node\n");
45 #endif
46 #if 0
47 Node* findNode = searchList(listhead,3);
48 if(findNode)
49 deleteNodeList2(listhead,findNode);
50 traverseList(listhead);putchar(10);
51 #endif
52
53 #if 0
54 Node* findNodePre = searchListPre(listhead,3);
55 if(findNodePre)
56 deleteNodeList3(findNodePre);
57 traverseList(listhead);putchar(10);
58 #endif
59
60 #if 0
61 Node** findNode = searchList(listhead,3);
62 if(findNode)
63 deleteNodeList(findNode);
64 traverseList(listhead);putchar(10);
65
66 #endif
67
68 #if 0
69 reverseList(listhead);
70 traverseList(listhead);putchar(10);
71 #endif
72
73 #if 0
74 printf("len = %d\n",getLenList(listhead));
75 #endif
76
77 #if 0
78 clearList(listhead);
79 // traverseList(listhead);putchar(10);
80 for(i = 7; i<15;i++)
81 {
82 insertList_end(listhead,i);
83 // insertList_head(listhead,i);
84 }
85 traverseList(listhead);putchar(10);
86
87 #endif
88
89 #if 0
90 destroyList(&listhead);
91 printf("listhead = %d",listhead);
92
93 #endif
94
95 #if 0
96 traverseList2(listhead);putchar(10);
97 #endif
98
99 #if 0
100
101 // selectSortDataUp(listhead);
102 // selectSortDataDown(listhead);
103 selectSortDataDown2(listhead);
104 traverseList(listhead);putchar(10);
105
106 #endif
107
108 #if 0
109 bubbleSortDataUp2(listhead);
110 traverseList(listhead);putchar(10);
111 #endif
112
113 #if 0
114 selectSortPointer(listhead);
115 traverseList(listhead);putchar(10);
116
117 #endif
118 #if 1
119 bubbleSortPointer(listhead);
120 traverseList(listhead);putchar(10);
121
122 #endif
123
124
125 return 0;
126 }