對於單向連結串列的10幾種常用演算法
阿新 • • 發佈:2018-11-03
list.c檔案如下
list.h檔案如下#include "list.h" /*返回head連結串列POS節點的位置*/ LINK list_moov_pos(LINK head,int pos){ LINK node = head; while(--pos) node = node->pNext; return node; } /*求連結串列長度*/ int list_length(LINK *head){ LINK node = *head; int i = 0; while(NULL != node){ i++; node = node->pNext; } return i; } /* 判斷連結串列是否為空 */ bool list_empty(LINK *head){ LINK node = *head; if(NULL == node) return true; else return false; } /* 對連結串列進行氣泡排序 */ LINK list_sort(LINK *head){ LINK node = *head; LINK p = NULL; LINK q = NULL; LINK cache = (LINK)malloc(sizeof(LIST_DATA)); if(NULL == cache) exit(-1); for (p = node; p != NULL; p = p->pNext){ for (q = p->pNext; q != NULL; q=q->pNext){ if ((p->data).nume > (q->data).nume) { cache->data = p->data; p->data = q->data; q->data = cache->data; } } } free(cache); return node; } /*刪除連結串列head中第POS個節點的資料*/ bool list_pos_dele(LINK *head, int pos){ if(NULL == *head ||(0 < pos && pos > list_length(head))) return false; if(1 == pos){ LINK node = *head; *head = node->pNext; free(node); }else{ LINK pre_node = NULL, now_node= NULL; pre_node = list_moov_pos(*head,pos-1); now_node = list_moov_pos(*head,pos); pre_node->pNext = now_node ->pNext; free(now_node); } return true; } /*刪除連結串列head頭POS個刪除*/ bool list_head_dele(LINK *head ,int pos){ if(NULL == *head || (0 < pos && pos > list_length(head))) return false; LINK node = NULL; node = list_moov_pos(*head, pos); *head=node->pNext; free(node); return true; } /*頭新增*/ void list_head_add(LINK *head, DATA data){ if(*head == NULL){ (*head) = (LINK)malloc(sizeof(LIST_DATA)); if(NULL == *head) exit(-1); (*head)->data = data; (*head)->pNext = NULL; }else{ LINK add_node = NULL; add_node = (LINK)malloc(sizeof(LIST_DATA)); if(NULL == add_node) exit(-1); add_node->data = data; add_node->pNext = *head; *head = add_node; } } /*尾巴新增*/ void list_end_add(LINK *head, DATA data){ if(*head == NULL){ (*head) = (LINK)malloc(sizeof(LIST_DATA)); if(NULL == *head) exit(-1); (*head)->data = data; (*head)->pNext = NULL; }else{ LINK node = *head, node_add = NULL; while(node->pNext != NULL) node = node->pNext; node_add = (LINK)malloc(sizeof(LIST_DATA)); if(NULL == node_add) exit(-1); node_add->data = data; node_add->pNext = NULL; node->pNext = node_add; } } /*任意改動*/ bool list_random_change(LINK *head, DATA data, int pos){ if(NULL == *head || (0 < pos && pos > list_length(head))) return false; LINK node = NULL; node = list_moov_pos(*head,pos); node->data = data; return true; } /*任意節點前面插入資料*/ bool list_random_insert(LINK *head, DATA data, int pos){ if(NULL == *head || (0 < pos && pos > list_length(head))) return false; if(pos==1){ LINK node = NULL; node = (LINK)malloc(sizeof(LIST_DATA)); if(NULL == node) exit(-1); node->data = data; //將name賦值給結構體指標*head中的name。 node->pNext=*head; *head = node; } else{ LINK node = NULL,add_node = NULL; add_node = (LINK)malloc(sizeof(LIST_DATA)); if(NULL == add_node) exit(-1); node = list_moov_pos(*head ,pos-1); add_node->data = data; add_node->pNext = node->pNext; node->pNext =add_node; } return true; } /*連結串列head1 和head2 各自有序,合併成一個連結串列依然有序(遞迴方法)*/ LINK list_merge_recursive(LINK *head1, LINK *head2) { LINK head = NULL; LINK node1 = *head1; LINK node2 = *head2; if(node1 == NULL) return *head2; if(node2 == NULL) return *head1; if(node1->data.nume <= node2->data.nume) { head = node1; head->pNext = list_merge_recursive(&(*node1).pNext, &node2); }else { head = node2; head->pNext = list_merge_recursive(&node1, &(*node2).pNext); } return head; } /*將連結串列逆序*/ LINK list_reverse(LINK *head){ LINK node = *head; if( node == NULL || (*node).pNext == NULL || (*node).pNext->pNext == NULL) return node; /*連結串列為空或只有一個元素則直接返回*/ LINK t = NULL; LINK q = node; LINK p = (*node).pNext; while(q != NULL){ t = q->pNext; q->pNext = p; p = q; q = t; } /*此時q指向原始連結串列最後一個元素,也是逆轉後的連結串列的表頭元素*/ (*node).pNext->pNext = NULL; /*設定連結串列尾*/ (*node).pNext = p; /*調整連結串列頭*/ DATA data; data = node->data; list_end_add(&node,data); list_pos_dele(&node,1); return node; } /*連線2個連結串列*/ LINK list_concatenate(LINK *head1,LINK *head2){ if(*head1 == NULL) return *head2; if(*head2 == NULL) return *head1; LINK node = *head1; while(node->pNext != NULL) node=node->pNext; node->pNext = *head2; return *head1; } /*銷燬連結串列*/ void list_free(LINK *head){ while(*head != NULL){ list_free(&(*head)->pNext); free(*head); *head = NULL; } }
#ifndef LIST_H #define LIST_H #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <string.h> #include <stdbool.h> typedef struct list{ char name[1024]; int nume; }DATA; typedef struct list_all{ DATA data; struct list_all *pNext; }LIST_DATA; typedef LIST_DATA* LINK; #include "list.h" /*返回head連結串列POS節點的位置*/ LINK list_moov_pos(LINK head,int pos); /*求連結串列長度*/ int list_length(LINK *head); /* 判斷連結串列是否為空 */ bool list_empty(LINK *head); /* 對連結串列進行氣泡排序 */ LINK list_sort(LINK *head); /*刪除連結串列head中第POS個節點的資料*/ bool list_pos_dele(LINK *head, int pos); /*刪除連結串列head頭POS個刪除*/ bool list_head_dele(LINK *head ,int pos); /*頭新增*/ void list_head_add(LINK *head, DATA data); /*尾巴新增*/ void list_end_add(LINK *head, DATA data); /*任意改動*/ bool list_random_change(LINK *head, DATA data, int pos); /*任意節點前面插入資料*/ bool list_random_insert(LINK *head, DATA data, int pos); /*連結串列head1 和head2 各自有序,合併成一個連結串列依然有序(遞迴方法)*/ LINK list_merge_recursive(LINK *head1, LINK *head2); /*將連結串列逆序*/ LINK list_reverse(LINK *head); /*連線2個連結串列*/ LINK list_concatenate(LINK *head1,LINK *head2); /*銷燬連結串列*/ void list_free(LINK *head); #endif
main.c檔案如下
#include "list.h" LINK head = NULL; void add_head()//往頭新增資料 { int i; DATA node; for(i = 0; i < 5; i++){//連續新增5個數據 sprintf(node.name,"add head %d\0",i); node.nume = i; list_head_add(&head,node); } } void add_tail()//往尾新增資料 { int i; DATA node; for(i = 0; i < 5; i++){//連續新增5個數據 sprintf(node.name,"add tail %d\0",i); node.nume = i; list_end_add(&head,node); } } void add_arbitrarily(int pos)//任意插入 { int i; DATA node; //設定要插入的資料 strcpy(node.name,"arbitrarily"); node.nume = 100; //執行 list_random_insert(&head,node,pos); } void Any_change(int pos)//任意改動 { int i; DATA node; //新資料 strcpy(node.name,"Any change"); node.nume = 101; //執行 list_random_change(&head,node,pos); } void printf_data(LINK *head) { LINK node = *head; while(node != NULL){ printf("name=[%s] nume=[%d]\n",node->data.name,node->data.nume); node = node->pNext; } printf("\n"); } int main(int argc, char const *argv[]) { assert(head == NULL);//條件測試 printf("========往頭部新增資料=======1\n"); add_head(); printf_data(&head); printf("==========求連結串列長度=========2\n"); int len = 0; len = list_length(&head); printf("len = %d\n",len); printf("===========尾部新增==========3\n"); add_tail(); printf_data(&head); printf("====對連結串列進行氣泡排序=====4\n"); head = list_sort(&head); printf_data(&head); printf("=========任意節點前面插入========5\n"); add_arbitrarily(1);//往第一個節點前面插入資料 printf_data(&head); add_arbitrarily(4);//往第四個節點前面插入資料 printf_data(&head); printf("======任意節點資料改動=======6\n"); Any_change(1); printf_data(&head); Any_change(3); printf_data(&head); printf("========刪除頭N個數據========7\n"); list_head_dele(&head,2);//刪除頭2個 printf_data(&head); printf("=====刪除第POS位上的資料=====8\n"); list_pos_dele(&head,3);//刪除第3個 printf_data(&head); printf("=============倒序============9\n"); head = list_reverse(&head); /*倒序*/ printf_data(&head); printf("=====按nume編號合併連結串列======10\n"); int i; LINK test = NULL; DATA node; //生成新連結串列 for(i = 0; i < 5; i++){//連續新增5個數據 sprintf(node.name,"list merge recursive %d\0",i); node.nume = i; list_end_add(&test,node); } //head = list_merge_recursive(&head,&test);/*合併head 和 test 連結串列*/ // printf_data(&head); printf("====直接按順序連線2個連結串列====11\n"); /*按順序連線2個連結串列*/ head = list_concatenate(&test,&head);//test 在前 printf_data(&head); printf("======判斷連結串列是否為空=======12\n"); if(list_empty(&head)) printf("list is NULL\n"); else printf("list don't NULL\n"); printf("============銷燬連結串列=========13\n"); list_free(&head);//銷燬連結串列 printf_data(&head); printf("======判斷連結串列是否為空=======14\n"); if(list_empty(&head)) printf("list is NULL\n"); else printf("list don't NULL\n"); }