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 }