#include <iostream>
#include <iomanip>
using namespace std;
void show(int*a) //交换数据
{
for(int i=0;i<8;i++) cout<<setw(3)<<a[i];
cout<<endl;
}
void swap(int* a,int start,int second)
{
int temp=*(a+start);
*(a+start)=*(a+second);
*(a+second)=temp;
}
void sort(int* a,int start,int end)
{
show(a);
if(start>=end) return;
swap(a,start,(start+end)/2);//选择中值,作为标准进行二分
cout<<"选择中间替换"<<endl;show(a);
int current=start; //current记录最后一次交换时,较小的数据的索引
for(int i=start+1;i<=end;i++) //第一项(标准)数据,与后面所有数据比较
{
if(*(a+i)<*(a+start)) //如果小于标准(start),就移到前面
{
swap(a,++current,i);
cout<<i<<"和"<<current<<"位置交换"<<endl;
show(a);
}
else //这句可以无,只是为了演示交换情况
{
cout<<i<<"与"<<current<<"无交换"<<endl;
show(a);
}
}
cout<<"中值小左大右"<<endl;show(a);
swap(a,start,current); //关键:第一项(start)和最后一次较小数据索引交换
cout<<"中值换到后较"<<endl;show(a);
sort(a,start,current);
sort(a,current+1,end);
}
int main(int argc, char *argv[])
{
int a[8]={8,7,6,5,4,3,2,1};
sort(a,0,7);
show(a);
return 0;
}
总则: 在数列中选择一个任意数,以它为标准,比它小的放在其左边,比它大的放在右边。这样数列就分成两部分:左边较小部分,右边较大部分。
对于左边部分,也按上面,选择左边中任意一数,较小的再放左边,较大的放中边。
对于右边部分,同理。
这样一直“二分”下去,直到数据小于2的个数,就结束了。
实现: 实现时一般选中数据中间数(不固定,反正都是随意),反它与第一个交换。它成为第一个后,就以它为标准。对于后面的所有数列进行比较,如果比它小,
就前移,比它大,就不管。于是它后面的数列总的趋势就是左小右大。最后把第一个和最后一次小数据交换。
这样,就完成了上面“总则”里面的,把数列分成两部分,左边较小、右边较大。达到“二分”目的。
于是,再用递归,对左边的“二分,对右边的”二分“,一直递归下去。
递归的终止:当分到只有一个数据时,递归就终止了。
看一下演示情况:基准选择索引中间,对应的就是5,把5弄到最前面,让后面的所有数据与5来比较,小的放在左侧,大的放在右侧:
第一次完成后,可以看到左侧是4321,右侧是687,然后最后次交换的索引是4,对应的数据是1,把第一项(即数据5)与索引4(即数据1)进行交换。
因此第一次彻底完成!!! 于是以5为轴,它的左边全小于5,它的右边全大于5.
下面对5的左边(较小部分)进行递归,再按照上面的进行排列:
这就是对前面部分按照前的进行比较。就不细说了
另一个同学写的,感觉很奇妙,参悟参悟:
#include<stdio.h>
int a[10]={9,8,7,6,5,4,3,2,1,0};
void prt(int n)
{
int i;
for(i=0;i<=n;i++)
printf("%d ",a[i]);
printf("\n");
}
void quicksort(int a[],int l,int h)
{
if(l>h) return;
int i=l;
int j=h;
int key=a[i];
while(i<j)
{
while(i<j&&a[j]>=key) j--;
if(i<j) a[i++]=a[j];
while(i<j&&a[i]<=key) i++;
if(i<j) a[j--]=a[i];
}
a[i]=key;
quicksort(a,0,i-1);
quicksort(a,i+1,h);
}
int main()
{
quicksort(a,0,9);
prt(9);
return 0;
}