/*--------------------------------------------------------------------------------------------
快速排序法
排序原理:找出一个中间元素,让左边的值均小于它,右边的值均大于它.然
后再分别对左边和右边进行同样处理的方式排序.第一次用到的
中间元素可以取中间元素也可以取第一个元素,这里取第一个元
素,所以先找右边第一个小于它的值,将该值赋给第一个元素,还
是用一个短小的例子说明吧!(最基本的原理应该是用的分治法.)
下面拿10个元素为例进行说明:
---------------------------------------------------------
23 45 34 5 765 74 657 88 99 87
---------------------------------------------------------
第一次: left=0;
right=9;
调用Find_Mind(ar,left,right)分析如下:
temp=ar[left]=ar[0]=23;
1.在left右边寻找第一个小于23的元素(5),并把它赋给
ar[left],此时排序结果:
--------------------------------------------------------
5 45 34 5 765 74 657 88 99 87
---------------------------------------------------------
此时:left=0+1=1;(赋值语句结束后需要将left右移一位)
right=3;
2.在right左边从left(1)开始寻找第一个大于5的元
素(45),然后将其赋给ar[right],此时排序结果:
---------------------------------------------------------
5 45 34 45 765 74 657 88 99 87
---------------------------------------------------------
此时:left=1;
right=1;(赋值语句结束后需要将right左移一位)
第二次:是在Quick_Sort(ar,left,mid-1);这步的递归调用规程中,但是需
要注意,这里的left是主函数在调用Quick_Sort(ar,0,n-1)是传递
来的实参0,注意区这里的left和Find_Mid()中的left,实在不行可
用其他字母代替Find_Mid()中的left和right便可.但是这时传递的
left和min-1都是0,所以被if(left<right)语句挡住不能进入{}内
部求mid了,这时便要将控制权返回给调用Quick_Sort(ar,left,mid-1);
函数的下一个可执行语句,就是Quick_Sort(ar,mid+1,right);将上
次求的的mid和主函数参来的right带入为Quick_Sort(ar,2,9);这时
满足if(left<right),所以会调用Find_Mid()函数,继续求中间值.
步骤同第一次相同,具体参数如下:
mid=1;
right=9;
调用Quick_Sort(ar,mid+1,right);
中间的n次.................................
直到调用的Quick_Sort()中的两个参数相差为1时,便得出结果.
对以上的数组,输出结果应为:
1 : left = 1 right = 1
2 : left = 2 right = 2
3 : left = 3 right = 3
4 : left = 9 right = 9
5 : left = 5 right = 5
6 : left = 8 right = 8
7 : left = 7 right = 7
ar[10] = 5 23 34 45 74 87 88 99 657 765
--------------------------------------------------------------------------------------------*/
快速排序法
排序原理:找出一个中间元素,让左边的值均小于它,右边的值均大于它.然
后再分别对左边和右边进行同样处理的方式排序.第一次用到的
中间元素可以取中间元素也可以取第一个元素,这里取第一个元
素,所以先找右边第一个小于它的值,将该值赋给第一个元素,还
是用一个短小的例子说明吧!(最基本的原理应该是用的分治法.)
下面拿10个元素为例进行说明:
---------------------------------------------------------
23 45 34 5 765 74 657 88 99 87
---------------------------------------------------------
第一次: left=0;
right=9;
调用Find_Mind(ar,left,right)分析如下:
temp=ar[left]=ar[0]=23;
1.在left右边寻找第一个小于23的元素(5),并把它赋给
ar[left],此时排序结果:
--------------------------------------------------------
5 45 34 5 765 74 657 88 99 87
---------------------------------------------------------
此时:left=0+1=1;(赋值语句结束后需要将left右移一位)
right=3;
2.在right左边从left(1)开始寻找第一个大于5的元
素(45),然后将其赋给ar[right],此时排序结果:
---------------------------------------------------------
5 45 34 45 765 74 657 88 99 87
---------------------------------------------------------
此时:left=1;
right=1;(赋值语句结束后需要将right左移一位)
第二次:是在Quick_Sort(ar,left,mid-1);这步的递归调用规程中,但是需
要注意,这里的left是主函数在调用Quick_Sort(ar,0,n-1)是传递
来的实参0,注意区这里的left和Find_Mid()中的left,实在不行可
用其他字母代替Find_Mid()中的left和right便可.但是这时传递的
left和min-1都是0,所以被if(left<right)语句挡住不能进入{}内
部求mid了,这时便要将控制权返回给调用Quick_Sort(ar,left,mid-1);
函数的下一个可执行语句,就是Quick_Sort(ar,mid+1,right);将上
次求的的mid和主函数参来的right带入为Quick_Sort(ar,2,9);这时
满足if(left<right),所以会调用Find_Mid()函数,继续求中间值.
步骤同第一次相同,具体参数如下:
mid=1;
right=9;
调用Quick_Sort(ar,mid+1,right);
中间的n次.................................
直到调用的Quick_Sort()中的两个参数相差为1时,便得出结果.
对以上的数组,输出结果应为:
1 : left = 1 right = 1
2 : left = 2 right = 2
3 : left = 3 right = 3
4 : left = 9 right = 9
5 : left = 5 right = 5
6 : left = 8 right = 8
7 : left = 7 right = 7
ar[10] = 5 23 34 45 74 87 88 99 657 765
--------------------------------------------------------------------------------------------*/
#include<stdio.h>
int Find_Mid(int ar[],int left,int right);
void Quick_Sort(int ar[],int lrft,int right);
int main(void)
{
int i,n;
puts("Input the number of elements to the array:");
scanf("%d",&n);
int ar[n]; //变长数组,编译器应支持C99标准
printf("Input %d elements of the array:\n",n);
for(i=0;i<n;i++) //读取数组元素
scanf("%d",&ar[i]);
Quick_Sort(ar,0,n-1);
printf("ar[%d] = ",n);
for(i=0;i<n;i++) //逐个打印数组元素
printf("%d ",ar[i]);
putchar('\n');
return 0;
}
void Quick_Sort(int ar[],int left,int right)
{
int mid;
if(left<right)
{
mid=Find_Mid(ar,left,right); //求中间位置
Quick_Sort(ar,left,mid-1); //递归调用,对左边进行相同方式的分发
Quick_Sort(ar,mid+1,right); //递归调用,对右边进行相同方式的分发
}
}
int Find_Mid(int ar[],int left,int right)
{
static int ct; //声明一个静态变量用于计算调用Find_Mid()的次数
int temp;
if(left<right)
{
temp=ar[left];
while(left<right)
{
while(left<right && ar[right]>=temp) //右侧寻找第一个小于temp的元素
right--;
if(left<right) //left<right说明找到了,所以将找到的元素赋值给s[left]
ar[left++]=ar[right];
while(left<right && ar[left]<temp) //左侧寻找第一个大于等于temp的元素
left++;
if(left<right) //left>right说明找到了,所以将找到的元素赋值给s[left]
ar[right--]=ar[left];
}
ct++;
}
printf("%d : left = %d right = %d\n",ct,left,right);//输出每次调用后的left和right,应该相等
ar[left]=temp; //将比较的元素赋给找到的位置
return left;
}