使用二级指针简化臃肿的代码

单链表的删除简直就是最最基础的知识了,从大二上数据结构到今天我一直都记得如果要删除单链表,那就一定要判断是不是头结点,教科书都是这么教我们的,简单写个例子

while(cur->next->value != key)
    cur = cur->next;
if(cur == head)
    //头结点
else
    //不是头结点
    cur->next = cur->next->next;
    free();

这段代码已经深深的印在了我的脑子里

删除单链表要使用它的pre指针作为判断,并且要考虑头结点的问题
意思就是我们在做删除的时候要拿到它的pre,但是这是单链表没有pre指针,所以需要我们对代码有些处理,使用
cur->next->value != key

这我相信是大部分人的思路,也是教科书的思路。这样做不好的地方在哪里,在比如你在定义二叉查找树的时候

typedef struct binary_search_tree
{
    int value;
    struct binary_search_tree *lchild;
    struct binary_search_tree *rchild;
}tree_t;

左孩子和右孩子都使用同一个pre,那就更别提B树了。这样带来的麻烦就是:在(以二叉查找树为例)删除操作时,你要多考虑很多种问题,你需要记录应该删除节点的pre指针,还要判断是lchild还是rchild,同时还需要判断是不是头结点。我实现了删除的代码,看看有多长

void delete(tree_t *bs_tree,tree_t **bs_parent,int index)
{
    tree_t *p,*t;
    if (bs_tree->rchild == NULL)
    {
        if (index == 0)
        {
            (*bs_parent)->lchild = bs_tree->lchild;
            bs_tree->lchild = NULL;
            free(bs_tree);
        }
        else if (index == 1)
        {
            (*bs_parent)->rchild = bs_tree->lchild;
            bs_tree->lchild = NULL;
            free(bs_tree);
        }
        else
        {
            *bs_parent = bs_tree->lchild;
            free(bs_tree);
        }
    }
    else if (bs_tree->lchild == NULL)
    {
        if (index == 0)
        {
            (*bs_parent)->lchild = bs_tree->rchild;
            bs_tree->rchild = NULL;
            free(bs_tree);
        }
        else if (index == 1)
        {
            (*bs_parent)->rchild = bs_tree->rchild;
            bs_tree->rchild = NULL;
            free(bs_tree);
        }
        else
        {
            *bs_parent = bs_tree->rchild;
            free(bs_tree);
        }
    }
    else
    {
        p = bs_tree;
        t = bs_tree->lchild;

        while(t->rchild != NULL)
        {
            p = t;
            t = t->rchild;
        }

        if (p == bs_tree)
        {
            t->rchild = p->rchild;
            p->rchild = NULL;
            if (index == 0)
            {
                (*bs_parent)->lchild = t;
            }
            else if (index == 1)
            {
                (*bs_parent)->rchild = t;
            }
            else
            {
                (*bs_parent) = t;
            }
        }
        else
        {
            bs_tree->value = t->value;
            p->rchild = NULL;
            free(t);
        }
    }
}

void delete_value(tree_t *bs_tree,int key,tree_t **bs_parent,int index)
{
    if (bs_tree->value < key)
    {
        bs_parent = &bs_tree;
        delete_value(bs_tree->rchild,key,bs_parent,1);
    }
    else if (bs_tree->value > key)
    {
        bs_parent = &bs_tree;
        delete_value(bs_tree->lchild,key,bs_parent,0);
    }
    else
    {
        if (index == 1 || index == 0)
        {
            delete(bs_tree,bs_parent,index);
        }
        else
            delete(bs_tree,bs_parent,-1);
    }
}

index 0表示左孩子,1表示右孩子,如果-1就是根节点。当然没有注释是因为我不希望你像我这么傻乎乎的做,你只需要知道你要考虑很多可能就好了。
多写一行代码就有一定的概率出错,于是我看到了这篇文章
http://coolshell.cn/articles/8990.html

一开始我是拒绝的。我觉得这不可能完成,这不对,即使二级指针也不能改变pre中的next的地址啊!!

那么我们看一个简单的例子吧

    int **p;
    int *b = malloc(sizeof(int));
    *b = 5;
    p = &b;
    **p = 3;
    printf("%d \n",*b );

应该输出几呢,3!这就是使用二级指针修改的核心原理。

这样,删除链表就这样了

void test_fun(link_t **l,int key)
{
    link_t **cur = l;
    link_t *entry = *cur;
    while(entry->value != key)
    {
        cur = &entry->next;
        entry = *cur;
    }

    (*cur) = entry->next;
    free(entry);
}

那么我上面的删除二叉查找树的代码就可以精简很多了。我不用考虑是不是左、右孩子,也不用考虑是不是根节点!肯定能让代码逻辑性更强的。

今天这份代码基本刷新了我对单链表的认识。。同样的功能可以如此优雅,也可以臃肿不堪:)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
辽B代驾管理系统对代驾订单管理、用户咨询管理、代驾订单评价管理、代驾订单投诉管理、字典管理、论坛管理、公告管理、新闻信息管理、司机管理、用户管理、管理员管理等进行集中化处理。经过前面自己查阅的网络知识,加上自己在学校课堂上学习的知识,决定开发系统选择小程序模式这种高效率的模式完成系统功能开发。这种模式让操作员基于浏览器的方式进行网站访问,采用的主流的Java语言这种面向对象的语言进行辽B代驾管理系统程序的开发,在数据库的选择上面,选择功能强大的Mysql数据库进行数据的存放操作。辽B代驾管理系统的开发让用户查看代驾订单信息变得容易,让管理员高效管理代驾订单信息。 辽B代驾管理系统具有管理员角色,用户角色,这几个操作权限。 辽B代驾管理系统针对管理员设置的功能有:添加并管理各种类型信息,管理用户账户信息,管理代驾订单信息,管理公告信息等内容。 辽B代驾管理系统针对用户设置的功能有:查看并修改个人信息,查看代驾订单信息,查看公告信息等内容。 辽B代驾管理系统针对管理员设置的功能有:添加并管理各种类型信息,管理用户账户信息,管理代驾订单信息,管理公告信息等内容。 辽B代驾管理系统针对用户设置的功能有:查看并修改个人信息,查看代驾订单信息,查看公告信息等内容。 系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。项目管理页面提供的功能操作有:查看代驾订单,删除代驾订单操作,新增代驾订单操作,修改代驾订单操作。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。新闻管理页面,此页面提供给管理员的功能有:新增新闻,修改新闻,删除新闻。新闻类型管理页面,此页面提供给管理员的功能有:新增新闻类型,修改新闻类型,删除新闻类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值