双向链表的归并排序C++实现(含注释,非递归)

双向链表的归并排序顾名思义是将归并排序运用到双向链表中,其与单向链表不同在需要进行两次连接,所以读者应当注意。同时也需要考虑所依靠的段前后的分段节点是否不会改变,导致算法失效。注意本实现方法中需要段前后段后的辅助接点。具体的实现代码如下,具体的实现都写有注释。同时终止条件即:下段的元素个数是否达到排序的要求也需要考虑清楚如何实现。

void __merge(Node *l, Node *mid, Node *r) {
    Node * currprev = l->prev(); //为了和前段链表连接
    Node * endnode = r->next(); //为了和后段链表连接
    auto i = l, j = mid;
    while (i != mid || j != endnode) { //当两段均到末端后退出循环
        if (i == mid) {
            currprev->next() = j; // 正向连接下一个应该连接的节点
            j = j->next();
        } //保证 i 不越界
        else if (j == endnode) {
            currprev->next() = i; // 正向连接下一个应该连接的节点
            i = i->next();
        } //保证 j 不越界
        else if (i->data() <= j->data()) {
            currprev->next() = i; // 正向连接下一个应该连接的节点
            i = i->next();
        } else {
            currprev->next() = j; // 正向连接下一个应该连接的节点
            j = j->next();
        }
        currprev->next()->prev() = currprev; // 反向连接下一个应该连接的节点
        currprev = currprev->next(); //后移一位
    }
    currprev->next() = endnode; //正向连接后段链表
    endnode->prev() = currprev; //反向连接后段链表
}

//查找item后的第n个节点,终止节点为end
Node *nthNext(Node *item, int n, Node *end) {
	if(item==nullptr) return end;
    for (int i = 0; i < n; ++i) {
        if(item == end)
            break;
        item = item->next();
    }
    return item;
}

void sort(Node *startNode, Node *endNode, int n) {
    Node * item,mid,end,nextitem;
    Node * startPrev = startNode->prev(); //用于获取开端节点
    Node * endNodeNext = endNode->next(); //用于获取末端节点
    for (int sz = 1; sz <= n; sz += sz) {
        item = startPrev->next();
        mid = nthNext(item, sz - 1, endNodeNext->prev()); //求当前段中位节点
        while (mid != endNodeNext->prev()) { //当mid之后仍然有元素时进行排序
            end = nthNext(mid, sz, endNodeNext->prev()); //求当前段末位节点
            nextitem = end != endNodeNext->prev() ? end->next() : nullptr; //得到下一段的起始节点
            if (mid->data() > mid->next()->data()) {
                __merge(item, mid->next(), end); //当前后段无序则进行归并
            }
            item = nextitem;
            mid = nthNext(item, sz - 1 , endNodeNext->prev());
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

FlameAlpha

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

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

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

打赏作者

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

抵扣说明:

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

余额充值