经典排序算法的详细分析及C++实现代码

1、冒泡排序  O(n2)
每一次把最大的移动到最右端,第一次从0~n-1中找到最大的放到n-1处,第二次从0~n-2中找到最大的放到n-2处……
class BubbleSort {
public :
     int * bubbleSort( int * A,  int n) {
         int i,j,temp =  0 ;
         for (i =  1 ;i < n;i++)
             for (j =  0 ; j < n - i;j++) {
             if (A[j] > A[j +  1 ]) {
                 temp = A[j +  1 ];
                 A[j +  1 ] = A[j];
                 A[j] = temp;
             }
         }
         return A;
     }
};
2、选择排序  O(n2)
先把0处的看作最小值,从1~n-1中找到比它小的值,交换;再把1处的看作最小值,从2~n-1中找到比他小的,交换;……
class SelectionSort {
public :
     int * selectionSort( int * A,  int n) {
         if (n ==  0 )  return A;
         int i,j,min =  0 ,temp;
         for (i =  0 ;i < n;i++) {
             min = i;
             for (j = i+ 1 ;j < n;j++) {
                 if (A[j] < A[min]) {
                     min = j;
                 }
             }
            temp = A[i];
            A[i] = A[min];
            A[min] = temp;                    
         }      
         return A;
     }
};

3、插入排序  O(n2)
先把0处看作已排序的序列,将1~n-1处逐个地与0处比较,若比0处小,则将其插入到已排序的序列中;……;假设0~3已排序,将4~n-1处依次与3处比较,若小于3处,则将其插入到0~3的适当位置;……
class InsertionSort {
public :
     int * insertionSort( int * A,  int n) {
         int i,j,k,temp;
         for (i =  1 ;i < n;i++) {
             k = i;
             for (j = i- 1 ;j >= 0 ;j--) {
             if (A[k] < A[j]) {
                 temp = A[k];
                 A[k] = A[j];
                 A[j] = temp;
                 k = j;
             }               
             }                     
         }
          return A;  
     }
};

4、归并排序(递归)  O(NlogN) 
先将序列分成2个子序列,再分成4个,……,直到所有子序列都只含一个元素;对每个子序列排序,再将相邻的两个已排序子序列归并为一个排序序列,依次类推,最后归并出原序列的排序序列。
class MergeSort {
public :
 
     void Merge( int * A, int start, int middle, int end) {
         int temp[end-start + 1 ];
         int k =  0 ;
         for ( int i = start,j = middle +  1 ;i <= middle || j <= end;k++) {
             if (i <= middle && j <= end) {
                 if (A[i] < A[j]) {
                 temp[k] = A[i];
                 i++;
             }
             else {
                 temp[k] = A[j];
                 j++;
             }
             }
             else if (i <= middle) {
                 temp[k] = A[i];
                 i++;
             }
             else {
                 temp[k] = A[j];
                 j++;
             }
                      
         }
         for ( int m =  0 ;m < k;m++)
             A[start + m] = temp[m];
     }
     void Divide( int * A, int start, int end) {

         if (start < end) {
             int m = (start + end)/ 2 ;
             Divide(A,start,m);
             Divide(A,m+ 1 ,end);
             Merge(A,start,m,end);
         }
        
     }
     int * mergeSort( int * A,  int n) {
         Divide(A, 0 ,n- 1 );
         return A;
     }
};

5、快速排序(递归)  O(NlogN)
先从序列中选取一个元素为基数,一般选最左边一个;两个指针i、j分别从序列的头尾向中间遍历;j从右到左找到小于基数的元素(j处),复制到基数处(i处),i++;然后i从左向右找到大于基数的元素(i处),复制到j处,j--;依次类推,直到i与j相遇使i>=j,while循环结束,此时已把序列分成左右两个子序列,左边小于基数,右边大于基数;再将左右子序列当做未排序序列进行递归。
class QuickSort {
public:
    void Quick( int * A, int  start, int  end) {
        if (start >= end)  return ;
        else {
             int  i = start,j = end;
             int  base = A[i];
             while  (i < j) {
                 while  (i < j && A[j] > base) j--;
                 if  (i < j) {
                    A[i] = A[j];
                    i++;
                }
                while (i < j && A[i] < base) i++;
                if (i < j) {
                    A[j] = A[i];
                    j--;
                }
            }
            A[i] = base;
            Quick(A,start,i - 1);
            Quick(A,i + 1,end);
        }
    }
     int * quickSort( int * A,  int  n) {
        // write code here
        Quick(A,0,n-1);
         return  A;
    }
};

6、堆排序 O(NlogN)
堆实际上是一种思想,不是一种数据存储结构,堆中数据的逻辑结构与完全二叉树一样,设总共有n个结点,则叶结点个数为n+1/2或者n/2,则非叶子结点个数为n-1/2或者n/2,当n能被2整除时为n/2,不能被整除时为n-1/2。
思路:
(1)堆化数组。给定一个长度为n的乱序数组,若要递增排序,则先将其堆化(按层序存储),即把原数组调整为大端堆。
(2)取堆顶元素放入数组末尾。每次将堆顶元素与数组末尾元素交换。
(3)调整交换元素后的堆。再从堆顶到第n-2个元素调整数组为大端堆,直到n-2=1为止,即堆中只剩下一个元素未放入排序序列为止。
class HeapSort {
public :
     
     void  heapify( int * A, int i, int n) {
         int j,temp;
         temp = A[i];
         j =  2 *i +  1 ;
         
         while (j < n) {
             if (j +  1 < n && A[j+ 1 ] > A[j]) j++;
             if (A[j] <= temp)  break ;
                 A[i] = A[j];
                 i = j;
                 j =  2 *i + 1 ;
 
         }
         A[i] = temp;
         return ;
     }
     
     int * heapSort( int * A,  int n) {
         // write code here
         int  temp;
         for ( int  m = n/ 2 -  1 ;m >=  0 ;m--)
             heapify(A,m,n);
         for ( int  k = n- 1 ;k >=  1 ;k--) {
             temp = A[k];
             A[k] = A[ 0 ];
             A[ 0 ] = temp;
             heapify(A, 0 ,k);
         }
         return  A;
     }
};


7、希尔排序 O(NlogN)
插入排序的改进。每一次比较的步长是变化的。例如,长度为n的数组,第一次设置步长为n/2,认为前n/2个数已经排序,从第n/2+1个开始,将其逐个与第1个、2个……比较,大于则交换,小于则不做操作。然后减小步长,继续以上步骤直到步长变为1.
class ShellSort {
public :
     int * shellSort( int * A,  int n) {
         // write code here
         int span = n/ 2 ;
         int i,j,temp;
         
         while (span >=  1 ) {
             for (i = span;i < n;i++) {
                 j = i - span;
                 while (j >=  0 ) {
                     if (A[j] > A[i]) {
                         temp = A[j];
                         A[j] = A[i];
                         A[i] = temp;                           
                     }
                     j -= span;
                 }
             }
             span--;
         }
         return A;
     }
};

8、计数排序 O(N)
(1)先确认待排序数组A元素的取值范围,相当于找出最大值max和最小值min,桶C的大小必须要能包含所有的元素。
(2)顺序遍历数组A,把A[i]与桶C的下标对应起来,即,将C[A[i]-min]加1。这样A最小的元素与C的第一个下标对应,最大元素与C的最后一个下标对应。这个过程相当于把A中元素装入对应的桶中。
(3)顺序遍历桶C,把桶中元素按顺序倒出来,就是从小到大的已排序序列。
class CountingSort {
public :
     int * countingSort( int * A,  int n) {
         // write code here
         int max = A[ 0 ],min = A[ 0 ];
         for ( int i =  0 ;i < n;i++) {
             if (A[i] > max) max = A[i];
             if (A[i] < min) min = A[i];
         }           
         int sizeC = max - min +  1 ;
         int *C =  new int [sizeC];  
         for ( int i =  0 ;i < sizeC;i++)
             C[i] =  0 ;           
         for ( int j =  0 ;j < n;j++) {
             C[A[j]-min]++;
         }
         int z =  0 ;
         for ( int m =  0 ;m < sizeC;m++) {
             while (C[m] >  0 ) {
                 A[z] = m + min;
                 z++;
                 C[m]--;
             }            
         }
         delete []C;
         return A;
     }
};

9、基数排序 O(N)
先根据个位把各元素入桶,把桶中元素倒出来得到按个位排序的序列;再按照十位把各元素入桶,倒出来得到按十位排序的序列;以此类推……
注:A中数据小于2000.
一维数组实现:
class RadixSort {
public :
     int * radixSort( int * A,  int n) {
         // write code here
         int C[ 10 ];
         int divisor[ 5 ] = { 1 , 10 , 100 , 1000 , 10000 };
         int *B =  new int [n];
         for ( int i =  0 ;i <  4 ;i++) {
             for ( int j =  0 ;j <  10 ;j++)
                 C[j] =  0 ;
             for ( int k =  0 ;k < n;k++) {
                 int unit = (A[k]%divisor[i+ 1 ])/divisor[i];
                 C[unit]++;
             }
             for ( int j =  1 ;j <  10 ;j++)
                 C[j] += C[j- 1 ];
             
             for ( int k = n- 1 ;k >=  0 ;k--) {
                 int unit = (A[k]%divisor[i+ 1 ])/divisor[i];
                 B[C[unit]- 1 ] = A[k];
                 C[unit]--;
             }
             for ( int j =  0 ;j < n;j++)
             A[j] = B[j];          
         }
         delete []B;
         B = NULL;
         return A;
     }
};

二维数组实现:
class  RadixSort {
public :     
int * radixSort(int* A, int n) {
        // write code here
         vector < deque < int > > bucket(10);
         int  divisor[] = { 1 , 10 , 100 , 1000 , 10000 };
         for  ( int  i =  0 ;i <  4 ;i++) {
             for  ( int  j =  0 ;j < n;j++) {
                 int  unit = (A[j]%divisor[i+ 1 ])/divisor[i];
                bucket[unit].push_back(A[j]);
            }
             for  ( int  j =  0 , k =  0 ;j <  10 ;j++) {
                 while  (!bucket[j].empty()) {
                    A[k++] = bucket[j].front();
                    bucket[j].pop_front();
                }
            }
        }
         return  A;
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值