几种排序算法的总结

关于排序,在我的所学范围之内,时间复杂度比较低的,其实就这么几种,快速排序,堆排序,希尔排序,归并排序(主要指二路归并)

下面我就来介绍这几种排序算法

快速排序是应用最广泛和弹性最大的排序算法,他不仅可以进行简单的增排序和减排序,还可以进行一些比较特殊的排序

//这是函数的精华所在,分区函数
1
void Mypartition ( elementType A[],int low,int high,int *cutPoint ) 2 { 3 int x = A[low]; 4 while ( low < high ) 5 { 6 while ( high > low && A[high] >= x ) //这个地方可以看出来,快速排序是不稳定的 7 { 8 high--; 9 } 10 A[low] = A[high]; 11 while ( low < high && A[low] < x ) 12 { 13 low++; 14 } 15 A[high] = A[low]; 16 } 17 A[low] = A[high] = x; 18 *cutPoint = low; 19 } 20 void QuickSort ( elementType A[],int low,int high ) 21 { 22 if ( low < high ) 23 { 24 int cutPoint; 25 Mypartition ( A,low,high,&cutPoint ); 26 QuickSort( A,low,cutPoint - 1 ); 27 QuickSort( A,cutPoint + 1,high); 28 } 29 }

从上面我们可以看出,分区函数是最关键的函数,他的作用也绝不止步于此,下面就看他的一个应用

 1 //4. 快速排序的应用
 2 //*********************************************//
 3 //* 函数功能:所有三的倍数在最左面,除三余一的在中间,除三余二的在最右面*//
 4 //* 函数参数:数组指针,数组下标的下界和上界*//
 5 //* 返 回 值:无*//
 6 //*********************************************//
 7 void SpecialSort ( elementType A[],int low,int high )
 8 {
 9     int i = low;
10     int j = high;
11     //下面对整体进行三的倍数和非三的倍数的区分
12 
13     //先从左端找到第一个3的非倍数
14     while ( i < j && A[i] % 3 != 0 )
15     {
16         i++;
17     }
18     int x = A[i];
19 
20     while ( i < j )
21     {
22         while ( j > i && A[j] % 3 != 0 )
23         {
24             j--;
25         }
26         A[i] = A[j];
27         while ( i < j && A[i] % 3 == 0 )
28         {
29             i++;
30         }
31         A[j] = A[i];
32     }
33     A[j] = A[i] = x;
34     //下面对非三的倍数进行区分
35     j = high;
36     //先找到第一个除三余2的数
37     while ( i < j && A[i] % 3 == 1 )
38     {
39         i++;
40     }
41     x = A[i];
42 
43     while ( i < j )
44     {
45         while ( j > i && A[j] % 3 == 2 )
46         {
47             j--;
48         }
49         A[i] = A[j];
50         while ( i < j && A[i] % 3 == 1 )
51         {
52             i++;
53         }
54         A[j] = A[i];
55     }
56     A[i] = A[j] = x;
57 }

上面函数的应用是很能说明问题的,对一个数组按照不同的特征进行分类,这也正是分区函数的作用所在,除此之外,我们一定要注意,分区函数的关键是找到分界点,根据分界点进行不同特征的划分

希尔排序

希尔排序它是在直接插入排序的基础上设计的,插入排序的时间复杂度与数据的是否有序是息息相关的,所以希尔排序便是利用这一点,从不同的步长出发将数组分成几组进行排序,最后再对整体进行排序,时间复杂度就将会降低

 1 void ShellSort ( elementType A[],int n )
 2 {
 3     int dh,i,j;
 4     cout<<"请输入步dh:"<<endl;
 5     cin>>dh;
 6     int temp;
 7     while ( dh > 0 )
 8     {
 9         for ( i = dh;i < n;i++ )
10         {
11             temp = A[i];
12             for ( j = i - dh;j >= 0;j = j - dh )
13             {
14                 if ( temp < A[j] )
15                 {
16                     A[j + dh] = A[j];
17                 }
18                 else
19                 {
20                     break;
21                 }
22             }
23             A[j + dh] = temp;
24         }
25         dh = dh / 2;
26     }
27 }

堆排序

这个是在选择排序的基础上,将数组看做是顺序储存的树,经过特殊的筛选操作,一个个的找到最大值或者最小值,从而实现类似于直接选择排序的算法

 1 //4. 堆排序
 2 //*********************************************//
 3 //* 函数功能:堆排序(shift为核心的筛选算法)*//
 4 //* 函数参数:*//
 5 //* 返 回 值:空*//
 6 //*********************************************//
 7 //对以root为根节点,不超过n的数组调整为大根堆(注意调整是在已是大根堆的基础上调整的)
 8 void shift ( elementType A[],int root,int n )
 9 {
10     int i = root;
11     int x = A[i];   //保存根节点的值
12     int j = 2*i;
13 
14     while ( j < n )
15     {
16         if ( j + 1 <= n && A[j+1] > A[j] )
17         {
18             j = j + 1;
19         }
20         if ( x >= A[j] )
21         {
22             break;
23         }
24         else
25         {
26             A[i] = A[j];
27             i = j;
28             j = 2*j;
29         }
30     }
31     A[i] = x;
32 
33 }
34 //先建立堆,再输出堆
35 void HeapSort ( elementType A[],int n )
36 {
37     for ( int i = n / 2;i >= 0;i-- )
38     {
39         shift ( A,i,n );
40     }
41     for ( int i = n - 1;i > 0;i-- )
42     {
43         elementType temp;
44         temp = A[0];
45         A[0] = A[i];
46         A[i] = temp;
47 
48         shift( A,0,i - 1);
49     }
50 }
51 //************函数结束*************//

最后便是归并排序,我们这里只介绍二路归并排序,归并排序分为自顶向下和自底向上的排序,而就操作的复杂性而言,自顶向下是比较简单的,先划分再归并,利用递归

 1 //3. 二路归并排序
 2 //*********************************************//
 3 //* 函数功能:自上而下的二路归并排序*//
 4 //* 函数参数:数组下标的下界和上界*//
 5 //* 返 回 值:无*//
 6 //*********************************************//
 7 //归并函数,将la-lb和lb-lc的数组进行归并
 8 void Merge ( elementType A[],int la,int lb,int lc )
 9 {
10     int i = la;
11     int j = lb + 1;
12     int k = 0;
13     elementType C[lc-la+1];
14     while ( i <= lb && j <= lc )
15     {
16         if ( A[i] < A[j] )
17         {
18             C[k++] = A[i++];
19         }
20         if ( A[i] > A[j] )
21         {
22             C[k++] = A[j++];
23         }
24         if ( A[i] == A[j] )
25         {
26             C[k++] = A[i++];
27         }
28     }
29     while ( i <= lb )
30     {
31         C[k++] = A[i++];
32     }
33     while ( j <= lc )
34     {
35         C[k++] = A[j++];
36     }
37 //将C数组赋值回原来的A数组
38     for ( i = la,k = 0;i <= lc;i++,k++ )
39     {
40         A[i] = C[k];
41     }
42 }
43 //主函数
44 void MergeSort ( elementType A[],int low,int high )
45 {
46     if ( low < high )
47     {
48         int mid = ( low + high ) / 2;
49         MergeSort(A,low,mid);
50         MergeSort(A,mid+1,high);
51         Merge(A,low,mid,high);
52     }
53 }
54 //************函数结束*************//

猜你喜欢

转载自www.cnblogs.com/qianqianjunzi/p/10295328.html
今日推荐