• 各种排序算法及c语言实现


    插入排序O(n^2)

    冒泡排序 O(n^2)

    选择排序 O(n^2)

    快速排序 O(n log n)

    堆排序 O(n log n)

    归并排序 O(n log n)

    希尔排序 O(n^1.25)

    1.插入排序 O(n^2)

      一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:
      ⒈ 从第一个元素开始,该元素可以认为已经被排序
      ⒉ 取出下一个元素,在已经排序的元素序列中从后向前扫描
      ⒊ 如果该元素(已排序)大于新元素,将该元素移到下一位置
      ⒋ 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
      ⒌ 将新元素插入到下一位置中
      ⒍ 重复步骤2~5
      如果比较操作的代价比交换操作大的话,可以采用二分查找法来减少比较操作的数目。该算法可以认为是插入排序的一个变种,称为二分查找排序。
    void insert_sort(int* array,unsignedint n){
        int i,j;
        int temp;
        for(i=1;i<n;i++){
            temp=*(array+i);
            for(j=i;j>0&&*(array+j-1)>temp;j--){
                *(array+j)=*(array+j-1);
            }
            *(array+j)=temp;
        }
    }

    2.冒泡排序 O(n^2)

      冒泡排序算法的运作如下:
    1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
    2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
    3. 针对所有的元素重复以上的步骤,除了最后一个。
    4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
    5. #include<stdio.h>
      #defineSIZE8
      void bublle_sort(int a[],int n){//n为数组a的元素个数
          int i,j,temp;
          for(j=0;j<n-1;j++)
             for(i=0;i<n-1-j;i++)
                if(a[i]>a[i+1]){//数组元素大小按升序排列
                   temp=a[i];
                   a[i]=a[i+1];
                   a[i+1]=temp;
                }
            }
      int main(){
          int number[SIZE]={95,45,15,78,84,51,24,12};
          int i;
          bublle_sort(number,SIZE);
          for(i=0;i<SIZE;i++){
             printf("%d",number[i]);
          }
          printf("
      ");
      } 

     3.选择排序 O(n^2)

      void select_sort(int * a, int n){  
               register int i, j, min, t;
               for( i =0; i < n -1; i ++) { 
                     min = i; //查找最小值 
                    for( j = i +1; j < n; j ++)
                           if( a[min] > a[j]) 
                               min = j; //交换
                           if(min != i) {
                               t = a[min]; 
                              a[min] = a[i]; 
                              a[i] = t; 
                           }
                       } 
             }

    4.快速排序 O(n log n)

    void QuickSort(int a[],int numsize){//a是整形数组,numsize是元素个数
         int i=0,j=numsize-1;
         int val=a[0];//指定参考值val大小
         if(numsize>1){//确保数组长度至少为2,否则无需排序
             while(i<j{//循环结束条件
                for(;j>i;j--)//从后向前搜索比val小的元素,找到后填到a[i]中并跳出循环
                   if(a[j]<val){
                     a[i]=a[j];break;
                }
                for(;i<j;i++)//从前往后搜索比val大的元素,找到后填到a[j]中并跳出循环
                  if(a[i]>val){
                      a[j]=a[i];break;
                  }
             }
             a[i]=val;//将保存在val中的数放到a[i]中
             QuickSort(a,i);//递归,对前i个数排序
             QuickSort(a+i+1,numsize-1-i);//对i+1到numsize这numsize-1-i个数排序
        }
    }

    5. 堆排序 O(n log n)

       n个关键字序列Kl,K2,…,Kn称为(Heap),当且仅当该序列满足如下性质(简称为堆性质):
          (1)ki<=k(2i)且ki<=k(2i+1)(1≤i≤ n),当然,这是小根堆,大根堆则换成>=号。//k(i)相当于二叉树的非叶子结点,K(2i)则是左子节点,k(2i+1)是右子节点.
         若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:
          树中任一非叶子结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。
    // array是待调整的堆数组,i是待调整的数组元素的位置,nlength是数组的长度
    //本函数功能是:根据数组array构建大根堆
    void HeapAdjust(int array[], int i, int nLength)
    {
        int nChild;
        int nTemp;
        for (nTemp = array[i]; 2 * i + 1 < nLength; i = nChild)
        {
            // 子结点的位置=2*(父结点位置)+ 1
            nChild = 2 * i + 1;
            // 得到子结点中较大的结点
            if ( nChild < nLength-1 && array[nChild + 1] > array[nChild])
                ++nChild;
            // 如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点
            if (nTemp < array[nChild])
            {
                array[i] = array[nChild];
                array[nChild]= nTemp;
            }
            else
            // 否则退出循环
                break;
        }
    }
     
    // 堆排序算法
    void HeapSort(int array[],int length)
    {  
        int tmp;
        // 调整序列的前半部分元素,调整完之后第一个元素是序列的最大的元素
        //length/2-1是第一个非叶节点,此处"/"为整除
        for (int i = floor(length -1)/ 2 ; i >= 0; --i)
            HeapAdjust(array, i, length);
        // 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
        for (int i = length - 1; i > 0; --i)
        {
            // 把第一个元素和当前的最后一个元素交换,
            // 保证当前的最后一个位置的元素都是在现在的这个序列之中最大的
          ///  Swap(&array[0], &array[i]);
              tmp = array[i];
              array[i] = array[0];
              array[0] = tmp;
            // 不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的最大值
            HeapAdjust(array, 0, i);
        }
    }

     6.归并排序 O(n log n)

      将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个    有序表合并成一个有序,称为二路归并

    //归并操作
    void Merge(int sourceArr[], int targetArr[], int startIndex, int midIndex, int endIndex)
    {
        int i, j, k;
        for(i = midIndex+1, j = startIndex; startIndex <= midIndex && i <= endIndex; j++)
        {
            if(sourceArr[startIndex] < sourceArr[i])
            {
                targetArr[j] = sourceArr[startIndex++];
            }
            else
            {
                targetArr[j] = sourceArr[i++];
            }
        }
     
        if(startIndex <= midIndex)
        {
            for(k = 0; k <= midIndex-startIndex; k++)
            {
                targetArr[j+k] = sourceArr[startIndex+k];
            }
        }
     
        if(i <= endIndex)
        {
            for(k = 0; k <= endIndex- i; k++)
            {
                targetArr[j+k] = sourceArr[i+k];
            }
        }
    }
    //内部使用递归,空间复杂度为n+logn
    void MergeSort(int sourceArr[], int targetArr[], int startIndex, int endIndex)
    {
        int midIndex;
        int tempArr[100]; //此处大小依需求更改
        if(startIndex == endIndex)
        {
            targetArr[startIndex] = sourceArr[startIndex];
        }
        else
        {
            midIndex = (startIndex + endIndex)/2;
            MergeSort(sourceArr, tempArr, startIndex, midIndex);
            MergeSort(sourceArr, tempArr, midIndex+1, endIndex);
            Merge(tempArr, targetArr,startIndex, midIndex, endIndex);
        }
    }
     
    //调用
    int _tmain(int argc, _TCHAR* argv[])
    {
        int a[8]={50,10,20,30,70,40,80,60};
        int b[8];
        MergeSort(a, b, 0, 7);
        for(int i = 0; i < sizeof(a) / sizeof(*a); i++)
            cout << b[i] << ' ';
        cout << endl;
        system("pause");
        return 0;
    }
    7.希尔排序 O(n^1.25)
      先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
    void ShellSort(int a[], int n){
         int d, i, j, temp;
         for(d = n/2;d >= 1;d = d/2){
            for(i = d; i < n;i++){
                temp = a[i];
                for(j = i - d;(j >= 0) && (a[j] > temp);j = j-d){
                    a[j + d] = a[j];
                }
                a[j + d] = temp;
           }
        }
    }
  • 相关阅读:
    求一个整数的划分
    HDU 1028 Ignatius and the Princess III
    HDU1215
    博弈论(2)
    阶乘的位数
    母函数详解
    SpragueGrundy FunctionSG函数博弈论(3)
    图的基本操作邻接表类型
    HDU 1536 SG函数应用
    顺序栈的实现
  • 原文地址:https://www.cnblogs.com/izxcheng/p/3693309.html
Copyright © 2020-2023  润新知