自己編寫連結串列函式庫詳解
阿新 • • 發佈:2019-01-28
標頭檔案
#ifndef _LINKLIST_H #define _LINKLIST_H #define SUCCESS 10000 #define FAILURE 10001 #define TRUE 10002 #define FALSE 10003 typedef int ElemType; struct node { ElemType data; //資料域 struct node *next; //指標域 }; typedef struct node Node; int InitLinkList(Node **l); int InsertLinkList(Node *l, int n, ElemType e); int TraverseLinkList(Node *l, void(*p)(ElemType)); int LinkList_Len(Node *l); int LinkListEmpty(Node *l); int GetElem(Node *l, int n, ElemType *e); int LocateElem(Node *l, ElemType e, int (*p)(ElemType,ElemType)); int DeleteLinkList(Node *l, int p, ElemType *e); int ClearLinkList(Node *l); int DestroyLinkList(Node **l); int ReverseLinkList(Node *l); #endif
函式庫
#include "LinkList.h" #include <stdlib.h> //初始化條件:結構體指標已存在,並且傳入函式 //引數:Node **l l是一個指標,l的型別是Node **,l指向的型別是Node * //函式功能:建立一個首結點,該結點指標域為NULL int InitLinkList(Node **l) { (*l) = (Node *)malloc(sizeof(Node) * 1); if(NULL == *l) { return FAILURE; } (*l)->next = NULL; return SUCCESS; } //初始化條件;頭指標傳入函式,位置n不大於連結串列的長度 //引數:l 頭指標 n 要插入的位置 e 要插入的資料 //函式功能:在連結串列中新插入一個結點 int InsertLinkList(Node *l, int n, ElemType e) { Node *p = l; //定義一個指標指向頭結點 int k = 1; //移動的次數 if (NULL == l) //入參判斷 { return FAILURE; } while (k < n && p != NULL) //p移動到指向要插入位置前一個結點 { p = p->next; k++; } if (k > n || NULL == p) //所有意外情況都包含進去了 { return FAILURE; } Node *q = (Node *)malloc(sizeof(Node) * 1); // 給新節點分配空間 if (NULL == q) //檢查是否分配成功 { return FAILURE; } q->data = e; //給新建立的結點賦值 q->next = p->next; //新結點指向原來n處的結點 p->next = q; //原來n的前一個結點指向新結點 return SUCCESS; } //初始化條件,頭指標傳入函式 //引數:l 頭指標 p 函式指標,指向輸出函式 //函式功能:逐個輸出連結串列每個結點的值 int TraverseLinkList(Node *l, void(*p)(ElemType)) { Node *q = l; //定義一個指標指向頭結點 if (NULL == l) //入參判斷 { return FAILURE; } while (q->next != NULL) //當q指向最後一個結點的時候結束迴圈 { q = q->next; //q指向後一個結點 p(q->data); //輸出q指向結點的資料 } return SUCCESS; } //初始化條件:頭指標傳入函式 //引數:l頭指標 //函式功能:求出連結串列的長度 int LinkList_Len(Node *l) { if (NULL == l) { return FAILURE; } int len = 1; Node *p = l->next; while (p) { len++; p = p->next; } return len; } //初始化條件: //引數 l 頭指標 //函式功能,判斷連結串列是否為空 int LinkListEmpty(Node *l) { return (NULL == l->next) ? TRUE : FALSE; //頭結點之後沒有結點,為空連結串列 } //初始化條件:頭指標傳入函式,結點n不小於1,結點n要存在 //引數: l 頭指標 n 要檢視的位置 e 儲存檢視的那個結點的資料 //函式功能:得到連結串列中第n個結點的資料並返回其值 int GetElem(Node *l, int n, ElemType *e) { if (NULL == l || n < 1) { return FAILURE; } Node *p = l; int i; for (i = 0; i < n && p != NULL; i++) { p = p->next; } if (!p) { return FAILURE; } *e = p->data; return SUCCESS; } //初始化條件:頭指標傳入函式 //引數 l 頭指標 e 要查詢的元素 p 函式指標 指向比較函式 //函式功能:檢視e在連結串列中的第幾個結點 int LocateElem(Node *l, ElemType e, int (*p)(ElemType,ElemType)) { if (NULL == l) //入參判斷 { return FAILURE; } Node *q = l->next; //定義一個結點指向第一個節點 int len = 1; //結點的個數 while (q) //挨個比較e與結點資料是否相等 { if (TRUE ==p(e,q->data)) //如果相等,返回第幾個結點 { return len; } q = q->next; //指向下一個結點 len++; //結點個數加1 } return FAILURE; //如果沒有,返回失敗 } /* *引數: l 頭指標 * p 要刪除的位置,不能大於連結串列長度,不能小於1 * e要儲存p處結點的資料 *函式功能:刪除p處結點,並儲存其資料域的值 *返回值:SUCCESS/FAILURE */ int DeleteLinkList(Node *l, int p, ElemType *e) { if (NULL == l) //入參判斷 { return FAILURE; } int k = 1; //移動次數 Node *q = l; while (k < p && q != NULL) { q = q->next; k++; } //找到要刪除的位置前一個結點 if (k > p || NULL == q) { return FAILURE; } Node *n = q->next; //定義一個指標指向要刪除的結點 *e = n->data; //儲存要刪除結點的資料 q->next = n->next; //將要刪除的結點與要刪除的結點後面一個結點建立聯絡 free(n); //釋放給要刪除結點分配的空間 return SUCCESS; } /* *引數:l 頭指標 *實現功能:刪除除了頭結點外的所有結點 *返回值:SUCCESS/FAILURE */ int ClearLinkList(Node *l) { if (NULL == l) //入參判斷 { return FAILURE; } Node *p = l->next; //指標p指向第一個結點 while (p) //while迴圈刪除第一個結點以後所有結點 { l->next = p->next; free(p); p = l->next; } return SUCCESS; } /* * 引數:l頭指標 不為空 * 實現功能:銷燬連結串列,釋放為連結串列分配的空間 * 返回值:SUCCESS/FAILURE */ int DestroyLinkList(Node **l) { if (NULL == l) //入參判斷 { return FAILURE; } free(*l); //釋放連結串列空間 *l = NULL; //不變為空指標,會成野指標,記憶體洩漏 return SUCCESS; } /* *引數:l 頭指標 不為空 *實現功能:反轉連結串列 *返回值:TRUE/FALSE */ int ReverseLinkList(Node *l) { if (NULL == l) //入參判斷 { return FAILURE; } Node *p = l->next; //p指向第一個結點 l->next = NULL; //首結點與第一個結點斷開 while (p) //執行迴圈直到最後一個結點 { Node *q = p; //指標q指向p p = p -> next; //p指向下一個結點 q->next = l->next; //將q結點與頭結點後面一個結點相連 l->next = q; //頭結點與q相連 } return SUCCESS; }