使用C语言来实现一个通用的双向链表。利用这个链表来统计一篇文章的不同词数,针对不同单词和同一单词的不同拼写形式进行排序
本文利用了C语言来实现了一个通用的双向链表,其中双向链表的实现借鉴了
实现通用的双向链表(c语言实现)
读李先静《系统程序员成长计划》内容总结
这几篇文章。向其作者表示感谢。
首先我们先放运行的截图吧(我所用的文件为哈利波特1-3册,有27W+个单词)
- 首先,我们要创建一个链表,然后对于链表中的一些操作(创建链表,插入数据,查找数据)等等基本的操作进行实现。在这里我主要是借鉴了之前的文章。然后我自己根据我的需要加入了一点方法。
- 我自己实现的方法主要有:
1、一个检测此时的链表里面有没有我们的数据的方法,并且直接返回我们的数据位置,以及将我们的数据取出返回给我们的变量中
2、几个比较函数,主要是用于对单词的数量进行排序(冒泡排序),以及在取单词并且加入链表的时候进行一个检测的操作
3、对于统计单词的时候我自己设置的规则(区分大小写,不区分大小写,统计单词的拼写形式)**这段代码是付出了最多的心血的
4、针对链表中的数据进行了排序的操作(最简单的冒泡排序,对于其他的排序太复杂了。。)
5、其他细节,直接看代码吧 - 主要代码如下:针对一些特殊的地方我会进行具体的注释和讲解
dlist.h 的代码:
#include <stdlib.h>
#ifndef DLIST_H_INCLUDED
#define DLIST_H_INCLUDED
//用c语言的方式编译
#ifdef __cplusplus
extern "C"{
#endif /* _cplusplus */
//枚举,函数的返回值类型
typedef enum _DListRet
{
DLIST_RET_OK,
DLIST_RET_OOM,
DLIST_RET_STOP,
DLIST_RET_PARAMS,
DLIST_RET_FAIL
}DListRet;
//DList用于描述整个链表,定义在dlist.cpp中
struct _DList;
typedef struct _DList DList;
//销毁节点的回调
typedef void (*DListDataDestroyFunc)(void* ctx, void* data);
//节点数据比较回调
typedef int (*DListDataCompareFunc)(void* ctx, void* data);
//遍历链表时的回调
typedef DListRet (*DListDataVisitFunc)(void* ctx, void* data);
//可供调用者使用的链表操作函数
DList* dlist_create(DListDataDestroyFunc data_destroy, void* data_destroy_ctx);
DListRet dlist_insert(DList* thiz, size_t index, void* data);
DListRet dlist_prepend(DList* thiz, void* data);
DListRet dlist_append(DList* thiz, void* data);
DListRet dlist_delete(DList* thiz, size_t index);
DListRet dlist_get_by_index(DList* thiz, size_t index, void** data);
DListRet dlist_set_by_index(DList* thiz, size_t index, void* data);
size_t dlist_length(DList* thiz);
int dlist_hasnot(DList* thiz, DListDataCompareFunc cmp, void* ctx,void** data);
int dlist_find(DList* thiz, DListDataCompareFunc cmp, void* ctx);
DListRet dlist_foreach(DList* thiz, DListDataVisitFunc visit, void* ctx);
DListRet dlist_forquantity(DList* thiz, DListDataVisitFunc visit, void* ctx,int num);
void dlist_destroy(DList* thiz);
DListRet BubbleSort(DList* thiz,DListDataCompareFunc cmp);
#ifdef __cplusplus
}
#endif /* _cplusplus */
#endif // DLIST_H_INCLUDED
这个文件没什么可讲的,主要就是对于一些函数进行一个声明
dlist.c
#include "dlist.h"
//链表节点描述
typedef struct _DListNode
{
struct _DListNode* pre;
struct _DListNode* next;
void* data;
}DListNode;
//链表描述
struct _DList
{
DListNode* first;
DListDataDestroyFunc data_destroy;
void* data_destroy_ctx;
};
/************************** 内部使用的函数 ****************************/
//销毁一个节点的data成员,调用回调函数销毁
static void _dlist_destroy_data(DList* thiz, void* data)
{
if (thiz->data_destroy != NULL)
{
thiz->data_destroy(thiz->data_destroy_ctx, data);
}
return;
}
//产生一个节点
static DListNode* _dlist_create_node(DList* thiz, void* data)
{
DListNode* node = malloc(sizeof(DListNode));
if (node != NULL)
{
node->pre = NULL;
node->next = NULL;
node->data = data;
}
return node;
}
//通过index获取一个节点
static DListNode* _dlist_get_node(DList* thiz, size_t index, int fail_return_last)
{
DListNode* iter = thiz->first;
while (iter != NULL && iter->next != NULL && index > 0)
{
iter = iter->next;
index--;
}
if (!fail_return_last)
{
iter = index > 0 ? NULL : iter;
}
return iter;
}
//销毁一个节点
static void _dlist_destroy_node(DList* thiz, DListNode* node)
{
if (node != NULL)
{
node->next = NULL;
node->pre = NULL;
_dlist_destroy_data(thiz, node->data);
free(node);
}
return;
}
/************************** 调用者可使用的函数 ****************************/
//链表生成,参数分别为销毁节点data的回调以及回调的参数
DList* dlist_create(DListDataDestroyFunc data_destroy, void* data_destroy_ctx)
{
DList* thiz = malloc(sizeof(DList));
if (thiz != NULL)
{
thiz->first = NULL;
thiz->data_destroy = data_destroy;
thiz->data_destroy_ctx = data_destroy_ctx;
}
return thiz;
}
DListRet dlist_insert(DList* thiz, size_t index, void* data)
{
DListNode* node = NULL;
DListNode* cursor = NULL;
//构造节点
if ((node = _dlist_create_node(thiz, data)) == NULL)
{
return DLIST_RET_OOM;
}
//第一个节点
if (thiz->first == NULL)
{
thiz->first = node;
return DLIST_RET_OK;
}
//获取目标节点位置,1表示若超过链表长度length,则插在最后
cursor = _dlist_get_node(thiz, index, 1);
//插入链表中间位置
if (index < dlist_length(thiz))
{
//头插
if (thiz->first == cursor)
{
thiz->first = node;
}
//插入数据中间
else
{
node->pre = cursor->pre;
cursor->pre->next = node;
}
node->next = cursor;
cursor->pre = node;
}
//尾插
else
{
cursor->next = node;
node->pre = cursor;
}
}
//头插
DListRet dlist_prepend(DList* thiz, void* data)
{
return dlist_insert(thiz, 0, data);
}
//尾插
DListRet d