using namespace std;
void swap(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
}
void maxheapify(int A[],int heapsize,int i) //调整堆
{
int L=2*i+1; //左节点
int R=2*i+2; //右节点
int largest; //记录左右节点与其父节点的较大值
if(LA[i]) //比较左节点与其父节点值
{
largest=L;
}
else
{
largest=i;
}
if(RA[largest]) //比较右节点与其父节点值
{
largest=R;
}
if(largest!=i) //当当前最大值不属于父节点时
{
swap(A[i],A[largest]); //将左右节点中的较大值与父节点交换位置
maxheapify(A,heapsize,largest);
//判断子节点是否仍存在子节点,循环过滤,将最大数滤至堆顶
}
}
void buildmaxheap(int A[],int &heapsize,int
size) //建立大根堆
{
heapsize=size;
for(int i=(size-1)/2;i>=0;i--)
{
maxheapify(A,heapsize,i);
}
}
void heapsort(int A[],int size)
{
int heapsize;
buildmaxheap(A,heapsize,size); //建立大根堆
for(int i=size-1;i>0;i--) //调堆过程
{
swap(A[i],A[0]);
heapsize--;
maxheapify(A,heapsize,0);
}
}
int main()
{
int A[]={1,4,7,8,5,2,0,3,6,9};
heapsort(A,10);
for(int i=0;i<10;i++)
{
cout<<A[i]<<"
";
}
cout<<endl;
system("pause");
return 0;
}
随机化快速排序的基本思想:产生一个随机数(范围在0~length(A)-1),通过一躺排序将要排序的数据按此随机数分割成独立的两部分,其中一部分的所有数据都比另外一不部分的所有数据都要小,然后按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
#include
#include
using namespace
std;
void swap(int
&a,int &b)
{
int temp=a;
a=b;
b=temp;
}
int partition(int A[],int
p,int r) //按随机产生的数的值将A数组分成两个部分
{
int x=A[r];
int i=p-1;
for(int j=p;j
{
if(A[j]<=x)
{
i++;
swap(A[j],A[i]);
}
}
swap(A[r],A[i+1]);
return i+1;
}
int random(int a,int b)
//产生a~b-1随机数
{
time_t t;
srand((unsigned)time(&t));
return
rand()%(b-a)+a;
}
int randompartition(int
A[],int p,int r) //随机分割
{
int
i=random(p,r);
swap(A[i],A[r]);
return
partition(A,p,r);
}
void randomquicksort(int
A[],int p,int r)
{
if(p
{
int
q=randompartition(A,p,r);
randomquicksort(A,p,q-1);
randomquicksort(A,q+1,r);
}
}
int main()
{
int
A[]={1,4,7,8,5,2,0,3,6,9};
randomquicksort(A,0,9);
for(int
i=0;i<10;i++)
{
cout<<A[i]<<"
";
}
cout<<endl;
system("pause");
return 0;
}
程序图解:
注:1、图中列出了五趟排序,细心的会发现第四趟排序其实并没有起到什么作用,这就是因为是随机排序的原因,取到的随机数不一定能满足后面排序的要求,只是重复之前的操作。
2、图中橙色数字表示当前循环进行比较的两数,而红色数字则表示在比较后互换的数字。当然比较的数并不一定是当前互换的数字,同时互换的也并不是当前比较的数。同时如果某数既参与了比较又参与了互换,则以蓝色表示。
3、图中并未给出每次循环后p,r值得变化,可以自己去寻找规律。同时根据已知数据也很容易得出p、r值的变化。
7、计数排序
1)计数排序是一个非基于比较的排序算法,计数排序不是比较排序,排序的速度快于任何比较排序算法。但对输入的数据有附加的限制条件:
①输入的线性表的元素属于有限偏序集S;
②设输入的线性表的长度为n,|S|=k(表示集合S中元素的总数目为k),则k=O(n)。
2)计数排序的基本思想是对于给定的输入序列中的每一个元素x,确定该序列中值小于x的元素的个数。一旦有了这个信息,就可以将x直接存放到最终的输出序列的正确位置上。
3)算法的步骤如下:
①找出待排序的数组中最大和最小的元素
②统计数组中每个值为i的元素出现的次数,存入数组C的第i项
③对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
④反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1
#include<iostream>
using namespace std;
void countingsort(int A[],int B[],int size,int
max)
{
int *C=new
int[max+1];
for(int
i=0;i<=max;i++)
{
C[i]=0;
}
for(int i=0;i
{
++C[A[i]];
}
for(int
i=1;i<=max;i++)
{
C[i]=C[i]+C[i-1];
}
for(int
i=size-1;i>=0;i--)
{
B[C[A[i]]-1]=A[i];
C[A[i]]--;
}
}
int main()
{
int
A[]={1,4,7,8,5,2,3,6,9};
int B[9];
countingsort(A,B,9,9);
for(int
i=0;i<9;i++)
{
cout<<B[i]<<"
";
}
cout<<endl;
system("pause");
return 0;
}
程序图解:
1)基数排序(Radix
Sort)的基本思想:借助于多关键字排序的思想对单逻辑关键字进行排序的方法,先将关键字分解成若干部分,然后通过对各部分关键字的分别排序,最终完成对全部记录的排序。
2)本例待排序对象是数字,而由数字组成的关键字有10个不同的取值,其“基”为10。“基”即指关键字取值的范围。
#include<iostream>
#include<ctime>
using namespace std;
void counting(int A[],int count,int size)
{
int *C=new int[10];
int *D=new int[size];
for(int i=0;i<10;i++)
{
C[i]=0;
}
int *B=new int[size];
for(int i=0;i<size;i++)
{
B[i]=(A[i]/(int)pow(10.0,count));
C[B[i]]++;
}
for(int i=1;i<10;i++)
{
C[i]=C[i]+C[i-1];
}
for(int i=size-1;i>=0;i--)
{
D[C[B[i]]-1]=A[i];
C[B[i]]--;
}
for(int i=0;i<size;i++)
{
A[i]=D[i];
}
}
void radixsort(int A[],int count,int size)
{
for(int i=0;i<count;i++)
{
counting(A,i,size);
}
}
int main()
{
int A[10] = {278, 109, 63, 930, 589, 184, 505, 269, 8
,83};
radixsort(A,3,10);
for(int i=0;i<10;i++)
{
cout<<A[i]<<"
";
}
cout<<endl;
system("pause");
return 0;
}
程序图解:
注:如果细心可以发现,如果将基数排序的数组换成计数排序的数组,那么图解的过程和计数排序是一样的,因为这个时候就不需要多次按照基数去循环,这也就是说明为什么基数排序和计数排序一样是一个非基于比较的排序算法。其排序速度快于任何比较排序算法。
http://s11/mw690/002UMOy3gy6E5x4wcq6e2&690
1)桶排序的基本思想:将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)
2)桶排序以下列程序进行:
①根据给定数组构建一定量的空桶。
②遍历数组,并且把元素一个一个放到对应的桶子去。
③对每个不是空的桶子进行排序(本程序选用的是插入排序)。
④从不是空的桶子里把排好序的元素再依次输出。
#include<iostream>
using namespace
std;
struct
barrel
{
int a[10];
//存储进入桶内的元素值
int count;
//桶内元素个数
};
void insertersort(int A[],int
size)
{
for(int
i=1;i<size;i++)
{
int
value=A[i];
int
j=i-1;
while(j>=0&&A[j]>value)
{
A[j+1]=A[j];
j--;
}
A[j+1]=value;
}
}
void bucketsort(int A[],int
size)
{
int min =
A[0];
int max =
A[0];
for(int i=1;
i<size; ++i)
{
min = min
< A[i] ? min : A[i];
max = max
> A[i] ? max : A[i];
}
int num = (max - min+1 )/10 +
1; //计算需要的桶数量
barrel *B = new
barrel[num];
for(int
i=0;i<num;i++) //构建空桶
{
B[i].count=0;
}
for(int
i=0;i<size;i++)//分配不同数据进入不同桶中
{
int
pos=(A[i]-min+1)/10;
int
j=B[pos].count;
B[pos].a[j]=A[i];
B[pos].count+=1;
}
int j=0;
for(int
i=0;i<num;i++)
{
insertersort(B[i].a,B[i].count);
for(int
k=0;k<B[i].count;k++)
//按次序输出各桶排序元素
{
A[j]=B[i].a[k];
j++;
}
}
}
int main()
{
int data[] = {23, 12, 3, 54, 1,
98, 24, 34};
bucketsort(data,sizeof(data)/sizeof(int));
for(int
i=0;i<sizeof(data)/sizeof(int);i++)
{
cout<<data[i]<<"
";
}
cout<<endl;
system("pause");
return 0;
}
程序图解:
注:桶排序并不是比较排序,下图只给出桶排序中的分配元素过程,对于各桶内元素的排序可参看插入排序部分。