也没想象中那么神秘的数据结构-一种通用化双向链表设计(测试例程)

概述

本文作为《也没想象中那么神秘的数据结构-一种通用化双向链表设计》系列最后一篇,主要用于验证底层源码和对象设计的源码正确性,另外也向用户展示通用链表类的使用方法。

示例

★结合《也没想象中那么神秘的数据结构-一种通用化双向链表设计(底层源码)》和《也没想象中那么神秘的数据结构-一种通用化双向链表设计(对象设计)》中的源码使用。

★调用通用链表类创建整型链表对象(节点元素数据类型为整型)和字符串型链表对象(节点元素数据类型为字符串类型)。

★调用方法完成插入、删除、查找等相关操作。

★包含源文件dll_app.c(已验证通过)。

 dll_app.c

/**
 * @Filename : dll_app.c
 * @Revision : $Revision: 1.0 $
 * @Author : Feng(更多编程相关的知识和源码见微信公众号:不只会拍照的程序猿,欢迎订阅)
 * @Description : 通用双向链表测试应用代码
**/

#include "dll.h"
#include "class_dll.h"

/* 类操作, 带参数 */
#define CLASS_CALL(THIS,func,args...) ((THIS)->func(THIS,args))

/* 类操作, 无参数 */
#define CLASS_CALL_0(THIS,func) ((THIS)->func(THIS))

/* 元素节点定义,存放整型数据 */
struct t_int_node{
    struct t_node node;        /* 节点元素指针 */
    int  id;                /* 节点元素值 */
};

/* 判断节点中是否包含指定信息 */
int cmp_int_key(struct t_node *node, void *key)
{
    struct t_int_node *p_node = NULL;

    if ((node == NULL) || (key == NULL))
        return -1;

    p_node = (struct t_int_node *)node;

    return (p_node->id == *(int *)key ? 0 : -1);
}

/* 打印节点信息 */
void print_int_node(struct t_node *node)
{
    struct t_int_node *p_node = NULL;

    if (node == NULL)
        return;

    p_node = (struct t_int_node *)node;

    printf("%d ", p_node->id);
}

/* 整型链表测试,节点存放数据类型为整型 */
void int_test(void)
{
    int i;
    struct t_int_node *p_node = NULL;
    struct dll *p_dll = new_dll(cmp_int_key, print_int_node);

    if (p_dll == NULL)
        return;

    printf("*****integer list test*****\n");
    printf("list: ");
    /* 插入7个元素到链表, 链表:0 1 2 3 4 5 6 */
    for (i=0; i<7; i++) {
        if ((p_node = (struct t_int_node *)malloc(sizeof(struct t_int_node))) != NULL) {
            p_node->id = i;

            CLASS_CALL(p_dll, add, (struct t_node *)p_node);
        }
    }
    CLASS_CALL_0(p_dll, show);

    printf("---------------------------\n");

    /* 最后一个元素为6, 第四个元素为3,一共7个元素 */
    p_node = (struct t_int_node *)CLASS_CALL_0(p_dll, get_last);
    printf("last node is %d\n", p_node->id);

    p_node = (struct t_int_node *)CLASS_CALL(p_dll, get_n_th, 4);
    printf("4th node is %d\n", p_node->id);

    printf("list count is %d\n", CLASS_CALL_0(p_dll, get_count));

    printf("---------------------------\n");


    /* 删除第2元素1和元素值为5的元素,此时链表:0 2 3 4 6,第四个元素为4,一共5个元素 */
    CLASS_CALL(p_dll, del_n_th, 2);

    i = 5;
    CLASS_CALL(p_dll, del_key, &i);

    CLASS_CALL_0(p_dll, show);
    p_node = (struct t_int_node *)CLASS_CALL(p_dll, get_n_th, 4);
    printf("4th node is %d\n", p_node->id);
    printf("list count is %d\n", CLASS_CALL_0(p_dll, get_count));  
    printf("\n");
}


/* 元素节点定义,存放字符串数据 */
struct t_str_node{
    struct t_node node;        /* 节点元素指针 */
    char  name[16];            /* 节点元素值 */
};


/* 判断节点中是否包含指定信息 */
int cmp_str_key(struct t_node *node, void *key)
{
    struct t_str_node *p_node = NULL;

    if ((node == NULL) || (key == NULL))
        return -1;

    p_node = (struct t_str_node *)node;

    return (strcmp(p_node->name, (char *)key));
}

/* 打印节点信息 */
void print_str_node(struct t_node *node)
{
    struct t_str_node *p_node = NULL;

    if (node == NULL)
        return;

    p_node = (struct t_str_node *)node;

    printf("%s ", p_node->name);
}

/* 字符串型链表测试,节点存放数据类型为字符串型 */
void str_test(void)
{
    int i;
    struct t_str_node *p_node = NULL;
    struct dll *p_dll = new_dll(cmp_str_key, print_str_node);

    if (p_dll == NULL)
        return;
    printf("*****string list test*****\n");
    printf("list: ");

    /* 插入7个元素到链表, 链表:n0 n1 n2 n3 n4 n5 n6 */
    for (i=0; i<7; i++) {
        if ((p_node = (struct t_str_node *)malloc(sizeof(struct t_str_node))) != NULL) {
            sprintf(p_node->name, "n%d", i);
            p_dll->add(p_dll, (struct t_node *)p_node);
        }
    }
    CLASS_CALL_0(p_dll, show);

    /* 最后一个元素为n6, 第四个元素为n3,一共7个元素 */
    p_node = (struct t_str_node *)p_dll->get_last(p_dll);
    printf("last node is %s\n", p_node->name);

    p_node = (struct t_str_node *)p_dll->get_n_th(p_dll, 4);
    printf("4th node is %s\n", p_node->name);

    printf("list count is %d\n", p_dll->get_count(p_dll));
    printf("---------------------------\n");

    /* 删除第2元素n1和元素值为name5的元素(不存在,删除失败),此时链表:n0 n2 n3 n4 n5 n6,第四个元素为n4,一共6个元素 */
    p_dll->del_n_th(p_dll, 2);
    p_dll->del_key(p_dll, "name5");

    p_dll->show(p_dll);
    p_node = (struct t_str_node *)p_dll->get_n_th(p_dll, 4);
    printf("4th node is %s\n", p_node->name);

    printf("list count is %d\n", p_dll->get_count(p_dll));  
}

int main(void)
{
    int_test();
    str_test();

    return 0;   
}

结论

feng@feng-vm:~/share/dll$ gcc -o dll_test dll_app.c class_dll.c dll.c
feng@feng-vm:~/share/dll$ ./dll_test 
*****integer list test*****
list: 0 1 2 3 4 5 6 
---------------------------
last node is 6
4th node is 3
list count is 7
---------------------------
0 2 3 4 6 
4th node is 4
list count is 5

*****string list test*****
list: n0 n1 n2 n3 n4 n5 n6 
last node is n6
4th node is n3
list count is 7
---------------------------
n0 n2 n3 n4 n5 n6 
4th node is n4
list count is 6
feng@feng-vm:~/share/dll$ 

分析:

1. 示例在int_test()函数中调用通用链表对象类创建整型链表对象,并对链表进行元素插入、删除、查找操作。

2. 示例在str_test()函数中调用通用链表对象类创建字符串型链表对象,并对链表进行元素插入、删除、查找操作。

3. 由上示例可以看出,对于链表的操作,与节点数据类型构成并无太大的关系,只是在一些对数据需要进行特殊处理的时候才会有所区分,例如查找指定信息、输出数据信息等,此时我们可以采用模版模式,将差异化的接口抽象出来,通过子类进行实现,从而做到通用化的目的。

往期 · 推荐

也没想象中那么神秘的数据结构-一种通用化的双向链表设计(底层源码)

也没想象中那么神秘的数据结构-一环扣一环的“链表”(双向链表)

我用C语言玩对象,框架化的模板模式

我用C语言玩对象,偷偷关注着你的观察者模式(基类设计)

我用C语言玩对象,独一无二的单例模式

关注

更多精彩内容,请关注微信公众号:不只会拍照的程序猿,本人致力分享linux、设计模式、C语言、嵌入式、编程相关知识,也会抽空分享些摄影相关内容,同样也分享大量摄影、编程相关视频和源码,另外你若想要本文章源码请关注公众号:不只会拍照的程序猿,后台回复:数据结构源码,也可点击此处下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不只会拍照的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值