总述
记得在看《大话数据结构》的时候,author说不会快速排序,那么面试的时候很有可能会挂,实际上本人在第一次面试的时候确实被问到了快速排序算法,当时凭借着微弱的记忆,将这些内容和面试官说了一遍,后面看到面经里面面试者需要手写快速排序,觉得应该重温一下这个伟大的算法了...
学习方法
本人在学习的时候,感觉也是花了一些功夫,觉得最好的方法就是自己在草稿纸上面进行推导,写出一个数组,然后利用快速排序算法去推导,写出算法的过程,多写两遍,算法内容呀,编码呀都能一下子会了(仅仅是我这个小菜鸡的做法)....关于例子的话,我想偷个懒,我就不做了(尴尬脸)
细听分说
首先快速排序是基于冒泡排序的,它是对冒泡排序的一种改进,关于冒泡排序,请问度娘...,快速排序的思想也是非常简单的,,排序的过程中设置一个枢轴值,经过一次排序后,将整个数组分成两个部分,数组左边的值都小于该枢轴的值,数组右边的值都大于枢轴的值,这样就完成了一次排序。那么问题来了,关于枢轴值是怎么设置的呢?沿用严奶奶教材上面的做法,直接取第一个元素作为枢轴值(当然后面也有很多的优化:如三数取中呀什么的,但是貌似直接取第一个元素作为枢轴值和随机取一个元素作为枢轴值用的最多),于是,我们开始编写了分类的算法:
int partion(int A[], int low, int high)
{
int pivot = A[low]; // 第一个元素设为pivot值
while(low < high)
{
while(low < high && A[high] >= pivot)
{
--high;
}
A[low] = A[high];
while(low < high && A[low] <= pivot)
{
++low;
}
A[high] = A[low];
}
// 上面的大循环是low == high才结束,因此不是从右到左一次再从左到右一次就结束,而是直到pivot真的比左边都大比右边都小时结束
A[low] = pivot;
return low;
完美完成了任务,找到了划分点的下标,那么可以直接采用递归的方式再次运行这样的操作:
void QuickSort(int v[], int left, int right)
{
if (left < right)
{
int boundary = partition(v, left, right);
# 继续在左边进行划分
QuickSort(v, left, boundary);
# 在右边进行划分
QuickSort(v, boundary + 1, right);
}
}
好了好了,完美,心想着,面试官肯定对我的回答很满意,心里贼高兴,然后面试官来继续说了一句:XXX,我需要你用非递归算法实现以下,(wc...)
没办法呀,为了混口饭吃呀,您是上帝,我改行了吧,于是抓耳挠腮...(非递归版本实现)
注意:递归与非递归的转换主要是基于栈
void QuickSortNor(int v[], int left, int right)
{
if (left >= right)
return;
stack<int> s;
s.push(left);
s.push(right);
while (!s.empty())
{
int right = s.top();
s.pop();
int left = s.top();
s.pop();
if (left < right)
{
int boundary = partition(v, left, right);
// 左区间
s.push(left);
s.push(boundary);
// 右区间
s.push(boundary + 1);
s.push(right);
}
}
}
小结
好吧,补了一个知识点,开心...