两个遗留问题

在无表头单链表中删除指定值 x 的结点

循环遍历的实现方法如下:

template<typename T>
class WorkList : public LinkList<T>
{
protected:
    typedef typename LinkList<T>::Node  Node;

    /* 删除链表中的重复结点 */
    void rmdup(Node* head)
    {
        if(head != nullptr)
        {
            rmdup(head->next);  // 删除除去当前结点的子链表中的重复结点
            rmdup(head->next, head->value);  // 通过当前结点删除子链表中存在与当前结点值相同的结点
        }
    }

    /* head 链表的第一个结点,通过 val 删除相同值的结点 */
    void rmdup(Node*& head, int val)  // head 为引用是因为这个链表是不带头结点的链表,head 可能需要指向其他的结点
    {
        Node* pre = nullptr;  // pre 指向待删除结点的前一个结点
        Node* slider = head;  // slider 用于遍历链表

        while(slider)
        {
            /* 需要删除 slider 指向的结点 */
            if(slider->value == val)
            {
                /* 当要删除的结点为链表的第一个结点时 */
                if(slider == head)
                {
                    head = slider->next;  // 将 head 后移一个结点
                    delete slider;
                    slider = head;  // slider 重新指向链表的第一个结点
                }
                else
                {
                    Node* toDel = slider;

                    pre->next = toDel->next;
                    slider = toDel->next;
                    delete toDel;
                }
            }
            else
            {
                pre = slider;
                slider = slider->next;
            }
        }
    }

public:
    void rmdup()
    {
        rmdup(this->m_header.next);
    }
};

递归方法的实现如下:

template<typename T>
class WorkList : public LinkList<T>
{
protected:
    typedef typename LinkList<T>::Node  Node;

    /* 删除链表中的重复结点 */
    void rmdup(Node* head)
    {
        if(head != nullptr)
        {
            rmdup(head->next);  // 删除除去当前结点的子链表中的重复结点
            rmdup(head->next, head->value);  // 通过当前结点删除子链表中存在与当前结点值相同的结点
        }
    }

    /* head 链表的第一个结点,通过 val 删除相同值的结点 */
    void rmdup(Node*& head, int val)  // head 为引用是因为这个链表是不带头结点的链表,head 可能需要指向其他的结点
    {
        if(head)
        {
            if(head->value == val)
            {
                Node* toDel = head;

                head = head->next;
                delete toDel;

                rmdup(head, val);
            }
            else
            {
                rmdup(head->next, val);
            }
        }
    }

public:
    void rmdup()
    {
        rmdup(this->m_header.next);
    }
};

参数 head 为什么是引用?

因为此链表是不带头结点的,所以可能需要改变 head 的指向,而 head 并非全局变量和成员变量,所以需要加上引用。

如果不使用引用参数,rmdup() 函数原型该如何设计?

rmdup() 返回删除指定值后的第一个链表结点。

计算 n 个整型数的平均值

 

/* 常规做法,容易造成数据溢出 */
int toAverageClassic(int a[], int n)
{
    int ret = 0;

    if(n > 0)
    {
        for(int i = 0; i < n; i++)
        {
            ret += a[i];
        }

        ret /= n;
    }

    return ret;
}

/* 改进做法,有效的避免数据溢出 */
int toAverage(int a[], int n)
{
    int ret = 0;

    if(n > 0)
    {
        int m = 0;

        for(int i = 0; i < n; i++)
        {
            ret += a[i] / n;

            /* 求平均值的补偿部分, 这样做补偿部分不会溢出 */
            m += a[i] % n;
            ret += m / n;
            m %= n;
        }
    }

    return ret;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值