实现对数组和链表的快速排序

       在前面的博客中,已经写了关于数组和链表的选择排序、冒泡排序和插入排序。在这里,再次补充快速排序。快排的应用场景很多,其中面试中广泛使用的就是在无序数集中查找第K个大(或小)的数值。下面,我们来处理一下该排序:

       首先,在数组中进行快排,这是非常常见的排序方式:

//快速排序算法
void Quick_Sort(int *num, int fir, int sec)
{
    if(fir >= sec)
    return ;
    int temp = num[fir];
    int i = fir, j = sec;
    while(i<j)
    {
        while(i<j && num[j]>=temp)
            j--;
        num[i] = num[j];
        while(i<j && num[i]<=temp)
            i++;
        num[j] = num[i];
    }
    num[i] = temp;
    Quick_Sort(num,fir,i-1);
    Quick_Sort(num,i+1,sec);
}

      接下来,我们讨论在链表中进行快排。链表的快排在思路上稍微复杂一些,但是理解起来之后,代码就好些多了。这里,我推荐一篇理论不错的文章https://blog.youkuaiyun.com/otuhacker/article/details/10366563,建议大家读完之后,再看我的代码实现。

void Linklist_QuickSort(Node *begin, Node *end)
{
    if (begin == NULL || begin == end)
    return ;
    int key = begin->value;
    Node *slow = begin;//慢指针为了寻找key的合适位置;
    Node *fast = begin->next;
    while(fast != end)
    {
        if(fast->value < key)
        {   //slow和fast之间都是大于key的值;
            slow = slow->next;//原来的slow指的都是小于key的值,因此前进一步。
            swap(slow->value,fast->value);//将小于fast指向的小于key的值与大于key的值进行交换;
        }
        fast = fast->next;//无论怎样(交换后或不交换),快指针都要前行
    }//至此,在此次快排中key的具体位置已找到,就在slow处;
    swap(slow->value,key);//
    Linklist_QuickSort(begin,slow);//在左边递归进行快排
    Linklist_QuickSort(slow->next,end);//在右边递归进行快排
}

      当然,也有(数组的)非递归快排。这里,我只给出代码,如果大家有兴趣,可以自己搜查一下理论知识(抱歉,因为间隔时间较长,我把理论忘了?)。

int partition(vector<int> &vec,int low,int high)
{
    int pivot=vec[low];  //任选元素作为轴,这里选首元素
    while(low<high)
    {
        while(low<high && vec[high]>=pivot)
            high--;
        vec[low]=vec[high];
        while(low<high && vec[low]<=pivot)
            low++;
        vec[high]=vec[low];
    }
    //此时low==high
    vec[low]=pivot;
    return low;
}
void quicksort2(vector<int> &vec,int low,int high)
{
    stack<int> st;
    if(low<high)
    {
        int mid=partition(vec,low,high);
        if(low<mid-1)
        {
            st.push(low);
            st.push(mid-1);
        }
        if(mid+1<high)
        {
            st.push(mid+1);
            st.push(high);
        }
        //其实就是用栈保存每一个待排序子串的首尾元素下标,
        //下一次while循环时取出这个范围,对这段子序列进行partition操作
        while(!st.empty())
        {
            int q=st.top();
            st.pop();
            int p=st.top();
            st.pop();
            mid=partition(vec,p,q);
            if(p<mid-1)
            {
                st.push(p);
                st.push(mid-1);
            }
            if(mid+1<q)
            {
                st.push(mid+1);
                st.push(q);
            }
        }
    }
}

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值