C語言-------實現一個簡單的單向連結串列
阿新 • • 發佈:2019-01-09
編寫一個連結串列程式,在程式中實現簡單的功能
#include <stdio.h> #include <stdlib.h> struct node{ int num; char name[20]; struct node* next; //指向下一個地址的指標 }; //宣告一個連結串列,此時記憶體不分配記憶體 typedef struct node Node; //重新命名,便於書寫,太長了struct node typedef struct node* Link; //建構函式,實現傳過來的頭指標指向一個空的內容 void creat_node(Link *head) //形參為二級指標,操作的物件是指標變數的指標,這個概念我之前糾結了很久,很容易混.就單純的理解為對變數的值進行操作,這個變數是指標{*head = NULL; //*head是指標的內容} //頭插,連結串列中節點的插入方式 void insert_head(Link *head,Link p) //函式操作的形參是頭指標和新指標的地址,需要改變頭指標的指向,所以呼叫的是二級指標{Link a;a = *head; if(a == NULL){a = p;p -> next = NULL;}else{p -> next = *head;// *head -> next = NULL;這句被註釋掉了,這個是我當時犯的錯,這樣操作會使連結串列丟失*head = p;}} //尾插 void insert_tail(Link *head,Link p) //原理同頭插,尾插時注意新節點的next指標要指向NULL,在連結串列中迴圈時注意迴圈結束條件和迴圈體執行的操作 { Link a; a = *head; if( *head == NULL ) //頭指標指向空時,沒有節點 { *head = p; p -> next = NULL; } else { // *head -> next = p; 這句犯錯同上,連結串列會斷掉 while(a -> next != NULL) //這個迴圈,是在連結串列中找到它的最後一位,把新節點連線上去 { a = a -> next; } a -> next = p; p -> next = NULL; } } //釋放連結串列指標的空間 void release_node(Link head) //釋放空間不需要頭指標的移動,形參呼叫head的一級指標,傳head的指向地址,頭指標的內容改變時,頭指標的指向改變,效果就是頭指標的移動 { Link p; //定義一個指標,指向head,實現對連結串列的操作 p = head; while(p != NULL) { free(p); //釋放指標變數p指向的空間 p = p -> next; // p為變數,更新了p的值,效果是指標變數p現在指向p的下一個節點 } } //列印連結串列中的內容 void display_node(Link head) //對連結串列的操作,不需要移動head的位置,形參取head的一級指標 { Link a; //定義一個新指標變數a,指向head的位置 a = head; while(a != NULL) //列印節點內容,指標變數a指向下一個節點,實現後移的迴圈,直到a指向一個NULL { printf("num = %d name = %s\n",a -> num,a -> name); a = a -> next; } } //計算返回一個單向連結串列的長度 int length_node(Link head) //對連結串列的操作,不需要移動head的位置,形參取head的一級指標 { Link p; int i = 0; //記錄節點個數 p = head; while(p != NULL) //直到p指向的空間是NULL { i++; //i+1技術 p = p -> next; //p指向下一個節點 } return i; //返回值i是int的,要宣告函式的返回值 } //查詢連結串列中指定節點的內容 void check_node(Link head,int k) //對連結串列的操作,不需要移動head的位置,形參取head的一級指標,k為指定節點數 { Link p; p = head; if(p == NULL) printf("連結串列為空,無內容可查\n"); else { while(p != NULL) //找到連結串列中的指定節點打印出來 { if(p -> num == k) { printf("name = %s\n",p -> name); break; //列印完成後要記得退出迴圈 } else p = p -> next; //p指向p的後一位位元組 } } } //刪除指定節點 void delete_node(Link head,int x) //對連結串列的操作,不需要移動head的位置,形參取head的一級指標,k為指定節點數 { Link p,q; p = head; if(head == NULL) { printf("連結串列為空\n"); return ; } if(head -> next == NULL) //連結串列中只有一個節點 { if(p -> num == x) { free(p); p = NULL; return; } else { printf("沒有該節點\n"); return; } } while(p -> num != x) //找到指定節點刪除 { q = p; //記錄當前p指向的位置,p滿足迴圈條件時,q指向p的前一個節點地址 p = p -> next; } q -> next = p -> next; p -> next = NULL; //斷開p指向的位元組在連邊中的連線順序 free(p); //釋放空間 } //中間插, 新節點插到任意位置 void add_node(Link *head,Link m,int y) //需要討論head的指向,取二級指標,新節點的指標,插入節點的位置 { Link p,q; p = *head; while(p -> num != (y - 1)) //指標p停在要插入位置的前一個節點 { p = p -> next; } q = p -> next; p -> next = m; m -> next = q; m -> num = y; //完成指標的指向操作 } //指標num變數重賦值, void replay_num(Link head) { Link p; p = head; int i = 0; while(p != NULL) { p -> num = i + 1; p = p -> next; i++; } } //主函式 int main( ) { Link head = NULL;//head指向NULL 防止野指標 Link p = NULL; //定義一個指標P指向NULL,防止野指標 int k,x,y = 0,i = 0; Link m = NULL; //防止野指標 creat_node(&head); //head指向一個空 printf("請輸入姓名:\n"); for(i = 0;i < 3;i++) { p = (Link)malloc(sizeof(Node)); //malloc()函式分配Node大小的空間,型別轉換為Link型,指賦給p if(p == NULL)//空間分配失敗 { printf("malloc error!\n"); exit(-1); //結束程序 檔案包含stdlib.h } p -> num = i + 1; scanf("%s",p -> name); // insert_head(&head,p); //頭插 insert_tail(&head,p); //尾插 } display_node(head); printf("連結串列長度:%d\n",length_node(head)); printf("請輸入想要查詢的節點:\n"); scanf("%d",&k); check_node(head,k); printf("請輸入想要刪除的節點:\n"); scanf("%d",&x); delete_node(head,x); display_node(head); m = (Link)malloc(sizeof(Node)); //m指向一個新分配的空間 printf("請輸入想要插入的節點內容:\n"); scanf("%s",m -> name); printf("請輸入想要插入的節點位置:\n"); scanf("%d",&y); add_node(&head,m,y); replay_num(head); //呼叫add_node()函式後把num的內容重新排序 display_node(head); release_node(head); //釋放函式要放在最後 所有操作結束後釋放空間 return 0; }