使用C语言来实现一个通用的双向链表。利用这个链表来统计一篇文章的不同词数,针对不同单词和同一单词的不同拼写形式进行排序

使用C语言来实现一个通用的双向链表。利用这个链表来统计一篇文章的不同词数,针对不同单词和同一单词的不同拼写形式进行排序

本文利用了C语言来实现了一个通用的双向链表,其中双向链表的实现借鉴了
实现通用的双向链表(c语言实现)
读李先静《系统程序员成长计划》内容总结
这几篇文章。向其作者表示感谢。
首先我们先放运行的截图吧(我所用的文件为哈利波特1-3册,有27W+个单词)

测试文档字数

运行主界面

第一个功能

第二个功能

第三个功能

  1. 首先,我们要创建一个链表,然后对于链表中的一些操作(创建链表,插入数据,查找数据)等等基本的操作进行实现。在这里我主要是借鉴了之前的文章。然后我自己根据我的需要加入了一点方法。
  2. 我自己实现的方法主要有:
    1、一个检测此时的链表里面有没有我们的数据的方法,并且直接返回我们的数据位置,以及将我们的数据取出返回给我们的变量中
    2、几个比较函数,主要是用于对单词的数量进行排序(冒泡排序),以及在取单词并且加入链表的时候进行一个检测的操作
    3、对于统计单词的时候我自己设置的规则(区分大小写,不区分大小写,统计单词的拼写形式)**这段代码是付出了最多的心血的
    4、针对链表中的数据进行了排序的操作(最简单的冒泡排序,对于其他的排序太复杂了。。)
    5、其他细节,直接看代码吧
  3. 主要代码如下:针对一些特殊的地方我会进行具体的注释和讲解

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
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值