浅谈C++之冒泡排序、希尔排序、快速排序、插入排序、堆排序、基数排序性能对比分析(好戏在后面,有图有真相)(二)

2014-11-24 00:59:30 · 作者: · 浏览: 12
7 int Left(int i)
8 {
9 return 2*i;
10 }
11 int Right(int i)
12 {
13 return 2*i+1;
14 }
15
16 //把以第i个节点给子树的根的子树调整为堆
17 void MaxHeap(int *a,int i,int length)
18 {
19 int L=Left(i);
20 int R=Right(i);
21 int temp;
22 int largest; //记录子树最大值的下表,值可能为根节点下标、左子树下表、右子树下标
23 if (L<=length&&a[L-1]>a[i-1]) //length是递归返回的条件
24 {
25 largest=L;
26 }
27 else largest=i;
28 if (R<=length&&a[R-1]>a[largest-1]) //length是递归返回的条件
29 largest=R;
30 if (largest!=i)
31 {
32 temp=a[i-1];
33 a[i-1]=a[largest-1];
34 a[largest-1]=temp;
35 MaxHeap(a,largest,length);
36 }
37 }
38
39 void BuildMaxHeap(int *a,int length)
40 {
41
42 for (int i=length/2;i>=1;i--)
43 MaxHeap(a,i,length);
44 }
45
46 void HeapSort(int *a,int length)
47 {
48 BuildMaxHeap(a,length);
49 for (int i=length;i>0;i--)
50 {
51 int temp;
52 temp=a[i-1];
53 a[i-1]=a[0];
54 a[0]=temp;
55 length-=1;
56 MaxHeap(a,1,length);
57 }
58 }
  通过使用大根堆来排序,排序过程中主要的动作就是堆的调整。每次把堆的根节点存入到堆的后面,然后把最后一个节点交换到根节点的位置,然后又调整为新的堆。这样不断重复这个步骤就能把把一个数组排列的有序,时间复杂度为O(nlogn)。
  最后一种是比较特别的基数排序(属于分配式排序,前几种属于比较性排序)又称“桶子法”:
  基本思想是通过键值的部分信息分配到某些桶中,藉此达到排序的作用,基数排序属于稳定的排序,其时间复杂度为O(nlog(r)m),r为所采取的的基数,m为堆的个数,在某些情况下基数排序法的效率比其他比较性排序效率要高。
  
1 //基数排序
2 /////////////////////////////////////////////////
3 int GetMaxTimes(int *a,int n)
4 {
5 int max=a[0];
6 int count=0;
7 for (int i=1;i
8 {
9 if(a[i]>max)
10 max=a[i];
11 }
12 while(max)
13 {
14 max=max/10;
15 count++;
16 }
17 return count;
18 }
19
20 void InitialArray(int *a,int n)
21 {
22 for (int i=0;i
23 a[i]=0;
24 }
25
26 // void InitialArray1(int a[][],int m,int n)
27 // {
28 // for (int i=0;i
29 // for (int j=0;j
30 // a[i][j]=0;
31 // }
32
33 void RadixSort(int *a,int n)
34 {
35 int buckets[10][10000]={0};
36 int times=GetMaxTimes(a,n);
37 int index,temp;
38 int record[10]={0};
39 for (int i=0;i
40 {
41 int count=0;
42 temp=pow(10,i);//index=(a[j]/temp)%10;用来从低位到高位分离
43 for (int j=0;j
44 {
45 index=(a[j]/temp)%10;
46 buckets[index][record[index]++]=a[j];
47 }
48 //把桶中的数据按顺序还原到原数组中
49 for(int k=0;k<10;k++)
50 for (int m=0;m<100000;m++)
51 {
52 if(buckets[k][m]==0)break;
53 else
54 {
55 a[count++]=buckets[k][m];
56 //cout<
57 }
58 }
59 //重新初始化桶,不然前后两次排序之间会有影响
60 //buckets[10][10000]={0};
61 //record[10]={0};
62 //InitialArray1(buckets,10,10000);
63 for (k=0;k<10;k++)
64 for (int m=0;m<100000;m++)
65 {
66 if(buckets[k][m]==0)break;
67 else buckets[k][m]=0;
68 }
69 InitialArray(record,10);
70 }
71 }
  在这里需要注意的是由于局部变量桶过大可能会导致栈溢出而得不带结果,比如桶为int buckets[10][100000]={0};大小=(10*100000*4)/(1024*1024)=3.814M,如果栈的大小只有1M~3M的话就会溢出,就得不到结果,当然可以把这个局部变量改成全局变量。