05單鏈表的簡單實現與測試
阿新 • • 發佈:2018-12-02
/* *ListList.h */ #ifndef LINKLIST_H #define LINKLIST_H #include <stdio.h> #include <string.h> #include <stdlib.h> //讓使用者的資料包含這個結構體 typedef struct _LinkNode{ struct LinkNode *next; }LinkNode; //連結串列結構體 typedef struct _List{ LinkNode head; int size; }List; //初始化,建立一個新的連結串列 int InitList(List **list); //線性表已經存在,銷燬線性表 void DestroyList(List **list); //線性表L已經存在,將線性表置為空表 void ClearList(List *list); //線性表已存在,若線性表為空,返回0,否則返回-1 int ListEmpty(const List list); //線性表已存在,返回線性表的元素個數 int ListLength(const List *list); //線性表已存在,1≤i≤ListLength(list); 將線性表中的第pos個位置的元素返回給 int GetElem(const List *list, const int pos, void **elem); //線性表已存在,線上性表中的第pos個位置插入 void ListInsert(const List *list, int pos, void *elem); //線性表已存在,刪除線性表中的第pos個位置元素,並用elem返回其值 void ListDelete(const List *list, int pos, void **elem); //遍歷 void ListForeach(const List *list, void(*foreach)(void*)); #endif /* *ListList.c */ #include "LinkList.h" //初始化成功返回0,失敗返回-1 int InitList(List **list) { *list = (List*)malloc(sizeof(List)); if (NULL == list){ return -1; } (*list)->head.next = NULL; (*list)->size = 0; return 0; } void DestroyList(List **list) { if (NULL != *list){ free(*list); *list = NULL; } } void ClearList(List *list) { if (NULL != list){ list->head.next = NULL; list->size = 0; } } //線性表L已存在,若線性表為空,返回0,否則返回-1,傳入引數錯誤返回-2 int ListEmpty(const List *list) { if (NULL != list){ return -2; } if (0 != list->size){ return -1; } return list->size; } //獲取元素個數,出錯返回-1 int ListLength(const List *list) { if (NULL == list){ return -1; } List *mylist = (List*)list; return mylist->size; } //根據位置獲取值 int GetElem(const List *list, const int pos, void **elem) { if (NULL == list){ return -1; } const List *mylist = list; if ((mylist->size - 1) < pos || pos < 0){ return -1; } LinkNode *pCur = &(mylist->head); for (int i = 0; i < pos; i++){ pCur = pCur->next; } *elem = pCur->next; return 0; } void ListInsert(const List *list, int pos, void *elem) { //傳入引數判斷 if (NULL == list || NULL == elem){ return; } List *mylist = (List*)list; if (mylist->size < pos || pos < 0){ pos = mylist->size; } //找到pos位置結點的前一個結點 LinkNode *pCur = &(mylist->head); for (int i = 0; i < pos; i++){ pCur = pCur->next; } //將新結點插入連結串列 ((LinkNode*)elem)->next = pCur->next; pCur->next = (LinkNode*)elem; mylist->size++; } void ListDelete(const List *list, int pos, void **elem) { if (NULL == list){ return; } List *mylist = list; if (0 == mylist->size){ return; } if (mylist->size < pos || pos < 0){ return; } LinkNode *pCur = &(mylist->head); for (int i = 0; i < pos; i++){ pCur = pCur->next; } //快取待刪除的結點 LinkNode *pDel = pCur->next; //重新建立前驅後繼關係 pCur->next = pDel->next; mylist->size--; *elem = pDel; } void ListForeach(const List *list, void(*foreach)(void*)) { if (NULL == list || NULL == foreach){ return; } List *mylist = (List*)list; LinkNode *pCur = mylist->head.next; while (NULL != pCur){ foreach(pCur); pCur = pCur->next; } } /* *test.c */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include "LinkList.h" //使用者的資料,使用者的資料結構體的第一個成員必須包含規則的資料 typedef struct Maker{ LinkNode node; char name[64]; int age; }Maker; //測試輸出函式 void myPrint(void *data) { Maker *maker = (Maker*)data; printf("name: %s, age:%d\n", maker->name, maker->age); } int main() { Maker p1 = { NULL, "aaa1", 18 }; Maker p2 = { NULL, "aaa2", 19 }; Maker p3 = { NULL, "aaa3", 20 }; Maker p4 = { NULL, "aaa4", 21 }; Maker p5 = { NULL, "aaa5", 22 }; List *list; //初始化連結串列測試 if (InitList(&list) != 0){ printf("初始化連結串列失敗\n"); return -1; } //將資料插入連結串列 ListInsert(list, 0, (LinkNode *)&p1);//使用者的定址範圍縮小 ListInsert(list, 0, (LinkNode *)&p2); ListInsert(list, 0, (LinkNode *)&p3); ListInsert(list, 0, (LinkNode *)&p4); ListInsert(list, 0, (LinkNode *)&p5); //遍歷測試 ListForeach(list, myPrint); //指定位置獲取元素測試 Maker *m; if (-1 != GetElem(list, 2, &m)){ printf("m->name:%s,m->age:%d\n", m->name, m->age); } //獲取連結串列個數測試 printf("size:%d\n", ListLength(list)); DestroyList(&list); system("pause"); return 0; }