C语言 泛型链表的实现
生活随笔
收集整理的這篇文章主要介紹了
C语言 泛型链表的实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
參考文章:使用C語言實現“泛型”鏈表
文章目錄
- jiang工給的泛型鏈表例子,有點看不怎么懂,自己寫個看看:
- 實現方法
- 方法1:鏈表指針指向整個結點,結點中存放指向數據的指針
- 方法2:結構體數據作為結點,結點中存放指向prev、next的指針(好像這樣的話結構體數據確實不能直接作為結點)
jiang工給的泛型鏈表例子,有點看不怎么懂,自己寫個看看:
#include <stdio.h> struct list_head {struct list_head *next, *prev; };#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)//根據structd的成員獲取struct的地址 #define container_of(ptr, type, member) ((type *)(((char *)ptr) - (int)(&(((type*)0)->member))))//鏈表遍歷#define list_for_each(pos, head) \for (pos = (head)->next; pos != (head); pos = pos->next)#define list_for_each_prev(pos, head) \for (pos = (head)->prev; pos != (head); pos = pos->prev)#define LIST_HEAD_INIT(name) { &(name), &(name) }#define LIST_HEAD(name) \struct list_head name = LIST_HEAD_INIT(name)static inline void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next) {next->prev = new;new->next = next;new->prev = prev;prev->next = new; }static inline void list_add(struct list_head *new, struct list_head *head) {__list_add(new, head, head->next); }static inline void list_add_tail(struct list_head *new, struct list_head *head) {__list_add(new, head->prev, head); }static inline void __list_del(struct list_head * prev, struct list_head * next) {next->prev = prev;prev->next = next; }static inline void list_del(struct list_head *entry) {__list_del(entry->prev, entry->next); }typedef struct _student {int data ;struct list_head mylist; }student;int main() {LIST_HEAD(header_task);student s1 ={.data =1};student s2 ={.data =2};student s3 ={.data =3};struct list_head* pos;student* s;list_add(&s1.mylist,&header_task);list_add(&s2.mylist,&header_task);list_add(&s3.mylist,&header_task);list_for_each(pos, &header_task){s = container_of(pos, student, mylist);printf("data is %d\n",s->data);}printf("----------\n");list_del(&s2.mylist);list_for_each(pos, &header_task){s = container_of(pos, student, mylist);printf("data is %d\n",s->data);}printf("Hello World!\n");return 0; }實現方法
有一點懵逼,我的思路是,在結點中的數據域存放指向自定義數據結構的指針
另一種思路是在自定義數據結構中存放prev和next指針
思考一個問題,是先有數據,我們把數據串起來就,成了鏈表?
還是先有鏈表,我們再將數據一個個放進去?(好無聊的問題( ̄、 ̄))
那么我自己實現兩個版本吧,其中一個版本是鏈表指針指向整個結點,結點中存放指向數據的指針;另一個版本是將數據作為結點,像jianggong寫的那樣,但是可以將mylist(包含prev和next指針)寫在最上面,這樣就不必用相對地址去計算了
方法1:鏈表指針指向整個結點,結點中存放指向數據的指針
#include <stdio.h> #include <stdlib.h> #include <String.h>//定義結點 struct Node {void* data;struct Node* prev;struct Node* next; };//尾插結點 void list_add_tail(Node* p, void* e) {struct Node* n = (Node*)malloc(sizeof(Node));if (NULL != n) {n->data = e;Node* tmp = p->prev;p->prev = n;n->prev = tmp;n->next = p;tmp->next = n;} }//刪除結點 void list_del(Node* h, void* u) {while (NULL != h->next->data) {if (u == h->next->data) {Node* tmp = h->next;h->next = h->next->next;h->next->prev = h;if (NULL != tmp) {//if (NULL != tmp->data) {//free(tmp->data);free(tmp);printf("成功刪除結點!\n");return;//}}}else {h = h->next;}}printf("沒有找到要刪除的結點!\n"); }int main() {//創建鏈表Node header_task1 = { NULL, &header_task1, &header_task1 };//定義自定義結構體struct User{char name[20];char phone[20];};//創建自定義結構體u1(不是用malloc動態分配堆空間,不用free)User u1 = { "唐三藏", "18944443333" };User u2 = { "白骨精", "18922223333" };User u3 = { "豬八戒", "18911113333" };User u4 = { "牛魔王", "18900003333" };//尾插list_add_tail(&header_task1, &u1);list_add_tail(&header_task1, &u2);list_add_tail(&header_task1, &u3);list_add_tail(&header_task1, &u4);//遍歷//條件也可以是:node != &header_task1for (Node* node = header_task1.next; node->data != NULL; node = node->next) {printf("姓名:%s\t電話號碼:%s\n", ((User*)node->data)->name, ((User*)node->data)->phone);}//刪除某個結點list_del(&header_task1, &u1);//成功list_del(&header_task1, &u1);//沒有找到//遍歷//條件也可以是:node != &header_task1for (Node* node = header_task1.next; node->data != NULL; node = node->next) {printf("姓名:%s\t電話號碼:%s\n", ((User*)node->data)->name, ((User*)node->data)->phone);}return 0; }運行結果:
姓名:唐三藏 電話號碼:18944443333 姓名:白骨精 電話號碼:18922223333 姓名:豬八戒 電話號碼:18911113333 姓名:牛魔王 電話號碼:18900003333 成功刪除結點! 沒有找到要刪除的結點! 姓名:白骨精 電話號碼:18922223333 姓名:豬八戒 電話號碼:18911113333 姓名:牛魔王 電話號碼:18900003333方法2:結構體數據作為結點,結點中存放指向prev、next的指針(好像這樣的話結構體數據確實不能直接作為結點)
#include <stdio.h> #include <stdlib.h> #include <String.h>struct list_head {struct list_head* next;struct list_head* prev; };//尾插結點 void list_add_tail(list_head* head, list_head* new_node) {/*list_head* tmp = head->prev;head->prev = new_node;new_node->prev = tmp;tmp->next = new_node;new_node->next = head;*///根本不用temp啊!head->prev->next = new_node;new_node->prev = head->prev;head->prev = new_node;new_node->next = head; }//刪除結點 void list_del(list_head* head, list_head* del) {list_head* i = head;for (i = i->next; i != head; i = i->next) {if (i == del) {i->prev->next = i->next;i->next->prev = i->prev;//刪除結點也用不到tmp(只有單向鏈表增刪才用到tmp吧!)printf("刪除結點成功!\n");}} }int main() {//創建鏈表list_head header_task1 = {&header_task1, &header_task1 };//定義自定義結構體struct User{char name[20];char phone[20];list_head my_list;};//創建自定義結構體u1(不是用malloc動態分配堆空間,不用free)User u1 = { "唐三藏", "18944443333", {NULL, NULL} };User u2 = { "白骨精", "18922223333", {NULL, NULL} };User u3 = { "豬八戒", "18911113333", {NULL, NULL} };User u4 = { "牛魔王", "18900003333", {NULL, NULL} };//尾插list_add_tail(&header_task1, &u1.my_list);list_add_tail(&header_task1, &u2.my_list);list_add_tail(&header_task1, &u3.my_list);list_add_tail(&header_task1, &u4.my_list);list_head* pos1;User* u;//遍歷for (pos1 = header_task1.next; pos1 != &header_task1; pos1 = pos1->next) {u = (User*)((int)pos1 - (int)&(((User*)0)->my_list));printf("姓名:%s\t電話:%s\t\n", u->name, u->phone);}//刪除list_del(&header_task1, &u1.my_list);for (pos1 = header_task1.next; pos1 != &header_task1; pos1 = pos1->next) {u = (User*)((int)pos1 - (int)&(((User*)0)->my_list));printf("姓名:%s\t電話:%s\t\n", u->name, u->phone);}return 0; } 姓名:唐三藏 電話:18944443333 姓名:白骨精 電話:18922223333 姓名:豬八戒 電話:18911113333 姓名:牛魔王 電話:18900003333 刪除結點成功! 姓名:白骨精 電話:18922223333 姓名:豬八戒 電話:18911113333 姓名:牛魔王 電話:18900003333總結
以上是生活随笔為你收集整理的C语言 泛型链表的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言数据结构(大话数据结构——笔记1)
- 下一篇: C语言malloc动态分配内存分配失败怎