在前面的博客中,已经写了关于数组和链表的选择排序、冒泡排序和插入排序。在这里,再次补充快速排序。快排的应用场景很多,其中面试中广泛使用的就是在无序数集中查找第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);
}
}
}
}
1607

被折叠的 条评论
为什么被折叠?



