日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言实现通用链表初步(一)

發(fā)布時間:2025/3/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言实现通用链表初步(一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

注意:本文討論的是無頭單向非循環(huán)鏈表。

假設(shè)不采用Linux內(nèi)核鏈表的思路,怎樣用C語言實現(xiàn)通用鏈表呢?

一種常用的做法是:

typedef int element_t;

struct node_info

{

element_t data;

struct node_info *next;

};


其實這樣的鏈表算不上通用,因為無法同時使用不同的數(shù)據(jù)類型。參考網(wǎng)友的思路,以上可以改為下面的定義:

//無頭非循環(huán)單向鏈表 struct node_info {void *data;struct node_info *next; };

先看看頭文件:

#pragma once//無頭非循環(huán)單向鏈表 struct node_info {void *data;struct node_info *next; };struct student {char name[20];unsigned char age;};//for teststruct slist_info {struct node_info *first; //指向第一個節(jié)點void (*insert_head)(void *one_data, struct slist_info *info);//頭插int (*del)(struct node_info *node, struct slist_info *info);//刪除節(jié)點struct node_info* (*find)(struct slist_info *info,int(*compare)(void *dest,void *key),void *key);//這里的compare是回調(diào)函數(shù),由用戶提供void (*for_each)(const struct slist_info *info,void (*todo)(void *one_data));//遍歷,todo是回調(diào)函數(shù)void (*for_each_safe)(const struct slist_info *info,void (*todo)(void *one_data));//安全遍歷(覺得在這里這個方法意義不大)void (*invert)(struct slist_info *info);//反轉(zhuǎn)鏈表int (*is_dead_loop)(struct slist_info *info);//判斷是否有死環(huán),是返回1,不是返回0 };#define slist_is_empty(info) ((info)->first == NULL) //鏈表是否為空//構(gòu)造和析構(gòu) void slist_init(struct slist_info *info); void slist_destroy(struct slist_info *info);

與這個鏈表相關(guān)的操作如下。

1.插入元素(頭插法)

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include "slist.h"/*無頭非循環(huán)單鏈表*/ static void slist_insert_head(void *one_data, struct slist_info *info) {//頭插法assert(one_data != NULL && info != NULL);struct node_info *node = (struct node_info *)malloc(sizeof(struct node_info));//分配內(nèi)存assert(node!=NULL);node->data = one_data;//注意,這里只是簡單地把指針指向用戶的數(shù)據(jù),并沒有把用戶數(shù)據(jù)復(fù)制過來if (slist_is_empty(info)) {//1.空鏈表info->first = node;node->next = NULL;}else { //2. 非空node->next = info->first;info->first = node;} }
2.遍歷

static void slist_for_each(const struct slist_info *info,void (*todo)(void *one_data)) {assert(info != NULL && todo != NULL);struct node_info *cur = NULL;for (cur = info->first; cur != NULL; cur = cur->next) {todo(cur->data);} }static void slist_for_each_safe(const struct slist_info *info,void (*todo)(void *one_data)) {assert(info != NULL && todo != NULL);struct node_info *cur = NULL;struct node_info *Next = NULL;for (cur = info->first; cur != NULL; cur = Next) {Next = cur->next;//Next保存了下一個節(jié)點,如果這個節(jié)點被刪除了,那么下一個節(jié)點還可以找到todo(cur->data);} }
3.反轉(zhuǎn)(面試的時候,有可能會問到,直接背過好了!)

static void slist_invert(struct slist_info *info) {assert(info != NULL);struct node_info *Cur = NULL;struct node_info *Prev = NULL;struct node_info *Next = NULL;//1.移動Next 2.反向 3.移動Prev 4.移動Curfor (Cur = info->first; Cur != NULL; Cur = Next) {Next = Cur->next;Cur->next = Prev;Prev = Cur;}//修改頭指針,指向首節(jié)點info->first = Prev; }
4.查找


struct node_info *slist_find(struct slist_info *info,int(*compare)(void *dest,void *key),void *key) {assert(info != NULL && compare != NULL);struct node_info *cur = NULL;for (cur = info->first; cur != NULL; cur = cur->next) {if(compare(cur->data,key)==1)//回調(diào)函數(shù),把鏈表中的每一個數(shù)據(jù)和用戶傳入的關(guān)鍵字做比較,符合條件返回1return cur;//返回節(jié)點的地址給用戶}return NULL;//沒有找到返回空指針 }
注意,這里的第三個參數(shù)(關(guān)鍵字)也是用戶傳進來的。


5.構(gòu)造和析構(gòu)

void slist_init(struct slist_info *info) {//空鏈表, 第一個節(jié)點為NULLinfo->first = NULL;info->insert_head = slist_insert_head;info->del = slist_del;info->find = slist_find;info->invert = slist_invert;info->is_dead_loop = slist_is_dead_loop;info->for_each = slist_for_each;info->for_each_safe = slist_for_each_safe; }void slist_destroy(struct slist_info *info) {if(!slist_is_empty(info)){struct node_info *cur = NULL;struct node_info *Next = NULL;for (cur = info->first; cur != NULL; cur = Next) {Next = cur->next;//Next保存了下一個節(jié)點,如果這個節(jié)點被刪除了,那么下一個節(jié)點還可以找到free(cur);//釋放每個節(jié)點占用的內(nèi)存}}}
細心的讀者會發(fā)現(xiàn),好像有的函數(shù)沒有實現(xiàn)啊。下一篇博文我們再討論!


總結(jié)

以上是生活随笔為你收集整理的C语言实现通用链表初步(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。