算法:链表相关

题目

  1. 把2个有序单调递增的链表 合并到一个链表倒序输出。要求不产生dummy node
  2. 单链表快排(按交换值和指针实现)
  3. 单链表归并(快慢指针)

解法

涉及链表的插入操作,要考虑当前插入点的node 和前一个node,修改指针。链表倒序的场景方法有头插法和尾插法

#include <iostream>
#include <algorithm>
using namespace std;

struct ListNode {
    int _data;
    ListNode* _next;

    ListNode(int data):_data(data) {
        _next = NULL;
    }
};

class LinkList {
private:
    int _len;
    ListNode* _head;
public:
    LinkList() {
        _len = 0;
        _head = NULL;
    }

    ~LinkList() {
        if (_head) {
            ListNode* tmpNode = _head;
            _head = _head->_next;
            delete tmpNode;
            tmpNode = NULL;
        }
        _len = 0;
    }

    ListNode* GetHead() { return _head; }
    int GetLength() { return _len; }
    LinkList* Push(int dt) {
        ListNode* node = new ListNode(dt);
        ListNode* tmpNode = _head;
        if (!tmpNode) {
            _head = node;
            _len++;
            return this;
        }
        while (tmpNode->_next) {
            tmpNode = tmpNode->_next;
        }
        tmpNode->_next = node;
        _len++;
        return this;
    }

    /*
    Keep node as start point, save it's next to a tmpNode
    update tmpNode's pointer
    */
    ListNode* Reverse(ListNode* node) {
        if (!node) return node;

        ListNode* tmpNode = node;
        _head = node;
        while (node->_next) {
            tmpNode = node->_next;
            node->_next = tmpNode->_next;
            tmpNode->_next = _head;
            _head = tmpNode;
        }

        return _head;
    }

    ListNode* Reverse2(ListNode* node) {
        if(!node) return NULL;
        ListNode* first = NULL, * second = NULL;

        first = node;
        while (node->_next) {
            node = node->_next;
        }
        second = node;

        ListNode* tmp = first;
        while (first != second) {
            tmp = first;
            first = first->_next;
            tmp->_next = second->_next;
            second->_next = tmp;
        }

        return node;
    }

    /*
    Note: Take a primary link list as a template, split another list as element to insert to the template list
    Insert: Keep tow pointers, "_head" and "prev"
    such as insert new node: node
        tempNode = node;
        node = node->next;
        prev->next = tempNode;
        tempNode->next = _head;

    */
    ListNode* MergeList(LinkList* l) {
        ListNode* lhead = l->GetHead();
        ListNode* pre = NULL, *head = NULL, *tempNode = NULL;

        if (!lhead) return _head;
        if (!_head) return lhead;

        if(_head->_data >= lhead->_data) {
           head = lhead;
           lhead = lhead->_next;
           head->_next = _head;
           pre = _head;
           _head = _head->_next;
        }

        while (_head) {
            if (_head->_data <= lhead->_data) {
                pre = _head;
                _head = _head->_next;
            } else {
                tempNode = lhead;
                lhead = lhead->_next;
                pre->_next = tempNode;
                tempNode->_next = _head;
                pre = tempNode;
            }

            if (!lhead) break;
        }

        if (!_head&& lhead) { pre->_next = lhead; }
        _head = head;

        return _head;
    }

    // 交换的是ListNode里面的值,而不是2个节点
    ListNode* Partition(ListNode* left, ListNode* right) {
        int data = left->_data;
        ListNode* pSlow = left, *pQuick = left->_next;
        while (pQuick != right) {
            if (pQuick->_data < data) {
                pSlow = pSlow->_next;
                swap(pSlow->_data, pQuick->_data);
            }
            pQuick = pQuick->_next;
        }
        swap(pSlow->_data, left->_data);
        return pSlow;
    }

    void QuickSortInternal(ListNode* left, ListNode* right) {
        if (left == right) return;
        ListNode* mid = Partition(left, right);
        QuickSortInternal(left, mid);
        QuickSortInternal(mid->_next, right);
    }

    void QuickSort() {
        QuickSortInternal(_head, NULL);
    }

    ListNode* Merge(ListNode* left, ListNode* right) {
        ListNode dummy(0);
        static int i = 0;
        ListNode *p = &dummy;
        while(left && right) {
            if (left->_data < right->_data) {
                p->_next = left;
                left = left->_next;
            } else {
                p->_next = right;
                right = right->_next;
            }
            p = p->_next;
        }
        if (left) p->_next = left;
        if (right) p->_next = right;

        p = dummy._next;
        cout << "Round " << i++ << " : ";
        while (p) {
            cout << p->_data << ", ";
            p = p->_next;
        }
        cout << endl;
        _head = dummy._next;
        return _head;
    }


    ListNode *MergeRecursive(ListNode *a, ListNode *b) {
        if (!a) return b;
        if (!b) return a;
        if (a->_data <= b->_data) {
            a->_next = MergeRecursive(a->_next, b);
            return a;
        } else {
            b->_next = MergeRecursive(b->_next, a);
            return b;
        }
    }

    ListNode* MergeSort(ListNode* node) {
        if(!node || !node->_next) return node;

        ListNode* slow = node, *fast = node, *pre = NULL;
        while(fast && fast->_next) {
            pre = slow;
            slow = slow->_next;
            fast = fast->_next->_next;
        }
        pre->_next = NULL;
        ListNode *left = MergeSort(node); // slow 为中间结点了
        ListNode* right = MergeSort(slow);
        return Merge(left, right);
    }


    void Print(ListNode* tmp = NULL) {
        if (!tmp) tmp = _head;
        ListNode* node = tmp;
        while (node->_next) {
            cout << node->_data << "->";
            node = node->_next;
        }
        cout << node->_data << endl;
    }
};


int main() {
    LinkList* l1 = new LinkList();
    l1->Push(1)->Push(5)->Push(7)->Push(8)->Push(9)->Push(11)->Push(12)->Push(13);
    cout << "L1: ";
    l1->Print();

    LinkList* l2 = new LinkList();
    l2->Push(2)->Push(6)->Push(10)->Push(14)->Push(16);
    cout << "L2: ";
    l2->Print();

    l2->MergeList(l1);
    cout << "Merge: ";
    l2->Print();

    l2->Reverse(l2->GetHead());
    //tmpNode = l2->Reverse2(tmpNode);
    cout << "Reverse: ";
    l2->Print();

    LinkList* l3 = new LinkList();
    l3->Push(23)->Push(12)->Push(34)->Push(1)->Push(2)->Push(88)->Push(87)->Push(10);
    cout << "Origin L3: ";
    l3->Print();
    cout << "Sorted L3: " << endl;
    //l3->QuickSort();
    l3->MergeSort(l3->GetHead());
    l3->Print(l3->GetHead());
    delete l1;
    delete l2;
    delete l3;
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值