链表面试题-单链表排序(冒泡,快速,归并)

面试中单链表是一个被问及频率很高的问题,这几天同学面试中多次被问及,所以今天整理一下。


注:对链表排序时,只需要交换结点间的_data即可,如果想法是改变指针,那么只能是走弯路了。

结点类型

struct Node
{
    //构造函数
    Node(int data)
    :_next(nullptr)
    ,_data(data)
    {}

    Node* _next;
    int _data;
}

冒泡排序:
对于冒泡排序,想必任何一个程序猿都不会陌生。原理就不解释了。

void BubbleSortList(Node* Head)
{
    //空链表或者只有一个节点,则不做处理
    if(Head == nullptr || Head->_next == nunllptr)
         return;

    Node* cur = nullptr;//当前节点
    Node* next = nullptr;//下一个节点
    Node* tail = nullptr;//链表最后一个节点

    while(Head != tail){
        cur = Head;
        next = cur->_next;
        bool flag = false;//如果某一次遍历没有发生交换,则说明已经有序,直接退出
        while(next != tail){
            if(cur->_data > next->_data){
                std::swap(cur->_data,netx->_data);
                flag = ture;
                }
        cur = next;
        next = next->_next;
        }
    }
    if(flag == false)//说明没有发生交换
        break;

    tail = cur;
}

快速排序:

针对于快速排序,我了解三种快速排序的思路。
这里采用前后指针法:
具体的快速排序可见:http://blog.csdn.net/qq_36528114/article/details/78667034

void QuickSortList(Node* Head,Node* Tail)
{
    if(Head == nullptr || Head->_next == nullptr || Head == Tail)
            return;

    Node* cur = Head->_next;
    Node* pre = Head;
    int key = Head->_data;//以头节点作为基准值

    while(cur != tail){
        if(cur->_data < key){
            pre = pre->_next;
            if(pre != cur){
                std::swap(pre->_data,cur->_data);
            }
        }
        cur = cur->_next;
    }

    std::swap(Head->_data,pre->_data);//将基准值放到枢纽位置
    QuickSortList(Head,pre);
    QuickSortList(pre->_next,tail);
}

归并排序:
归并的思想还是再提一下:

  1. 获取当前序列的中间结点
  2. 将当前序列一分为二,然后合并成一个有序单链表
  3. 递归上面两步
//快慢指针法
Node* GetMidNode(Node* Head)
{
    if(Head == nullptr)
        return nullptr;
    if(Head->_next == nullptr)
        return Head;

    Node* Fast = Head->_next;
    Node* Slow = Head;
    while(Fast && Fast->_netx){
        Fast = Fast->_next->_next;
        Slow = Slow->_next;
    }
    return Slow;
}

Node* MergeTwoList(Node* Head1,Node* Head2)
{
    if(Head1 == nullptr)
        return Head2;
    if(Head2 == nullptr)
        return Head1;

    Node* newHead = nullptr;
    //让两个链表较小的头节点作为新链表的头
    if(Head1->_data <= Head2->_data){
        newHead = Head1;
        Head1 = Head->_next;
    }else{
            newHead = Head2;
            Head2 = Head2->_next;
        }

    Node* cur = newHead;//让newHead一直在链表头部,最后返回
    while(Head1 && Head2){
        if(Head1->_data <= Head2){
            cur->_next = Head1;
            cur = cur->_next;
            Head1 = Head1->_next;
        }else{
                cur->_next = Head2;
                cur = cur->_next;
                Head2 = Head2->_next;
            }
    }
    //链表1没走完
    if(Head1)
        cur->_next = Head1;

    //链表2没走完
    if(Head2)
        cur->_next = Head2;

    return newHead;
}

Node* MergeSortList(Node* Head)
{
    if(Head == nullptr)
        return nullptr;
    if(Head->_next == nullptr)
        return Head;

    Node* mid = GetMidNode(Head);
    //nextPart是另外一个区间的起始
    Node* nextPart = nullptr;
    if(mid){
        nextPart = mid->_next;
        mid->_next = nullptr;
    }

    return MergeTwoList(MergeSortList(Head),MergeSortList(nextPart));
}

猜你喜欢

转载自blog.csdn.net/qq_36528114/article/details/79566285