剖丁解牛式的快速排序分析
/// <summary>
/// 分拆,以第一个数为pivot,找到它应该在的位置(比它大的在它的右侧,比它小的在它的左侧)
/// </summary>
/// <param name="col">要排序的数组</param>
/// <param name="left">范围的开始端</param>
/// <param name="right">范围的结束端</param>
/// <returns>分割好后,返回pivot的位置,由于下一步的范围分割</returns>
private int Div(int[] col, int left, int right)
{
//先将pivot取出来,可以看做此位置已经空出来,这样到运作的最后肯定会有一个位置为空,这个空位就是用这个数来填补的。
//1.如果经过下一步while运算,left不变,最后还是通过col[left]=bases 将抽出的值填回来
int bases = col[left];
while (left < right)
{
//2.以一往一返为一轮
//2.1.“往”开始啦,开始扫描,比bases小的吗?如果不测范围缩小“--right”
while (left < right && col[right] > bases)
--right;
//2.1.1.如果有遇到比bases小的值,交换
if (left != right) //如果相等了,说明在这一轮中自己是最小的,也就不用交换,下一个while同理
{
//2.1.2.left vs right 将col[right]填补到开始时空出来位置来的col[left].
col[left] = col[right];
//2.1.3.如果这一趟交换了,那下一轮就不用再对比了,left变动没关系滴,只要空位right的位置不动就OK
left++;
}
//2.2.“返”开始啦
while (left < right && col[left] < bases) //这里的col[left]<bases值得斟酌,为什么要从left,而不是left+1开始?
++left;
if (left != right)
{
col[right] = col[left];
right--;
}
//至此完成一轮,接着继续
}
col[left] = bases;
return left; //这是基准最终停留的位置(由上一段代码可知)
}
/// <summary>
/// 快速排序,这里要清楚数组时引用类型
/// </summary>
/// <param name="col"></param>
/// <param name="left"></param>
/// <param name="right"></param>
public void QuickS(int[] col, int left, int right)
{
int i;
if (left < right)
{
i = Div(col, left, right); //得到分割点,分割点是不用再变动的,经过这一步,它的位置就确定了,快速排序就是以不断地得出分割点的方式来使数组有序起来的。
QuickS(col, left, i - 1);
QuickS(col, i + 1, right);
}
}
//Winform测试代码
private void button4_Click(object sender, EventArgs e)
{
ClientTest();
}
/// <summary>
/// 测试
/// </summary>
private static void ClientTest()
{
QuickSort qs = new QuickSort();
int[] array = new int[] { 12, 232, 345, 6, 234, 43, 2344, 232, 3, 56, 7898, 23341, 5676, 896 };
int len = array.Length;
qs.QuickS(array, 0, len - 1);
StringBuilder sb = new StringBuilder(12);
foreach (int item in array)
{
sb.Append(item.ToString() + "\t");
}
MessageBox.Show(sb.ToString());
}