排序算法总结

             在学习的过程中,渐渐发现自己不会的地方越来越多,学了很多东西,发现掌握的只是部分。排序算法一直在我心里是个疙瘩,今天打算把它好好整理整理。

             常见的几种排序算法总结:

类别排序方法 时间复杂度最好情况最坏情况空间复杂度稳定性备注
插入排序直接插入 O(n)O(n2)O(1)稳定n越小越好
 shell排序 O(n)O(n2)O(1)不稳定 
选择排序直接排序 O(n2)O(n2)O(1)不稳定n越小越好
 堆排序 O(nlog2n)O(nlog2n)O(1)不稳定n越大越好
交换排序冒泡排序 O(n)O(n2)O(1)稳定n越小越好
 快速排序 O(nlog2n)O(n2)O(nlog2n)不稳定n越大越好
归并排序  O(nlog2n)O(nlog2n)O(1)稳定n越大越好
 

1.直接插入排序:每次从无序序列中取出一个数,插入一个有序序列合适的位置,使他依然有序。

void Insert(int arr[],int val)
{
      for(int i=0;i<sizeof(arr),i++)
         for(int j=i;j>0;j--)
         {
                    if(arr[j]<arr[j-1])
                    {
                        int tmp=arr[j];
                        arr[j]=arr[j-1];
                        arr[j-1]=tmp;
                    }
         }
}
时间复杂度最好的情况是有序的情况下,为O(n),普通情况如上为O(n2);


2.shell排序:
   准备一个待排的数组[6,2,4,1,5,9],取关键字3,1;
   先每隔3个单位分成一组[6,1],[2,5],[4,9],再两两比大小,就变成了[1,2,4,6,5,9];
   再每隔1个单位分成一组,两两比大小,就成了[1,2,4,5,6,9];
  注:这个找关键字很重要


3.选择排序: 首先选择最小的数放在第一个位置,第二小的放在第二个位置。。。。直至有序
void select_sort(int a[],int n)
  {
    
    for(int i=0; i<n-1; i++)
    {
        int min_index = i; 
        
        for(int j=i+1; j<n; j++)
        {
            if(a[j] < a[min_index])
            {
                min_index = j;
            }
        }
        
        if( i != min_index)
        {
            int temp = a[i];
            a[i] = a[min_index];
            a[min_index] = temp;
        }
    }
}

4.堆排序:

堆的结构类似于完全二叉树,每个结点的值都小于或者等于其左右孩子结点的值,或者每个节点的值都大于或等于其左右孩子的值

堆排序过程将待排序的序列构造成一个堆,选出堆中最大的移走,再把剩余的元素调整成堆,找出最大的再移走,重复直至有序

 
  //堆排序
void HeapSort(int arr[],int len)
{    
    int i;    //初始化堆,从最后一个父节点开始    
    for(i = len/2 - 1; i >= 0; --i)
    {        
        Heapify(arr,i,len);    
    }    //从堆中的取出最大的元素再调整堆    
    for(i = len - 1;i > 0;--i) 
    {        
        int temp = arr[i];       
        arr[i] = arr[0];        
        arr[0] = temp;        //调整成堆        
        Heapify(arr,0,i);   
    }
}
再看 调整成堆的函数


void Heapify(int arr[], int first, int end)
{
    int father = first;
    int son = father * 2 + 1;
    while(son < end)
   {
        if(son + 1 < end && arr[son] < arr[son+1]) 
              ++son;
        //如果父节点大于子节点则表示调整完毕
        if(arr[father] > arr[son]) 
              break;
        else 
          {
             //不然就交换父节点和子节点的元素
             int temp = arr[father];
             arr[father] = arr[son];
             arr[son] = temp;
            //父和子节点变成下一个要比较的位置
            father = son;
            son = 2 * father + 1;
          }
    }
}
5.冒泡排序:比较相邻的元素,如果反序则交换,过程也是分为有序区和无序区,初始时有序区为空,所有元素都在无序区,经过第一趟后就能找出最大的元素,然后重复便可
void BubbleSort(int arr[], int n)
{    
     for (int i = 0; i < n - 1; i++) 
     {        
         for (int j = 0; j < n - i - 1; j++) 
         {            
             if (arr[j] > arr[j + 1]) 
             {                
                 int temp = arr[j];               
                 arr[j] = arr[j + 1];               
                 arr[j + 1] = temp;            
             }        
          }    
     }
}
6.快速排序:它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
排序函数
QuickSort(int arr[], int first, int end)


{


    int pivot = OnceSort(arr,first,end);//已经有轴值了,再对轴值左右进行递归


    QuickSort(arr,first,pivot-1);


    QuickSort(arr,pivot+1,end);


}


接下来就是一次排序的函数




void OnceSort(int arr[], int first, int end)


{ 


    int i = first,j = end; //当i<j即移动的点还没到中间时循环 


    while(i < j)


    {  //右边区开始,保证i<j并且arr[i]小于或者等于arr[j]的时候就向左遍历  


          while(i < j && arr[i] <= arr[j]) --j;  //这时候已经跳出循环,说明j>i 或者 arr[i]大于arr[j]了,如果i<j那就是arr[i]大于arr[j],那就交换 


          if(i < j)


          {   


              int temp = arr[i];   


              arr[i] = arr[j];   


              arr[j] = temp;  


          }  


          //对另一边执行同样的操作  


          while(i < j && arr[i] <= arr[j]) ++i;  


          if(i < j)


          {   


              int temp = arr[i];   


              arr[i] = arr[j];   


              arr[j] = temp;  


           } 


    } 


    //返回已经移动的一边当做下次排序的轴值 


    return i;


}
7.归并排序:将待排序序列分为两部分,依次对分得的两个部分再次使用归并排序,之后再对其进行合并首先,将一整个序列分成两个序列,两个会分成4个,这样分下去分到最小单位,然后开始合并
void Merge(int arr[], int reg[], int start, int end) 
{
    if (start >= end)return;
    int len = end - start, mid = (len >> 1) + start;

    //分成两部分
    int start1 = start, end1 = mid;
    int start2 = mid + 1, end2 = end;
    //然后合并
    Merge(arr, reg, start1, end1);
    Merge(arr, reg, start2, end2);


    int k = start;
    //两个序列一一比较,哪的序列的元素小就放进reg序列里面,然后位置+1再与另一个序列原来位置的元素比较
    //如此反复,可以把两个有序的序列合并成一个有序的序列
    while (start1 <= end1 && start2 <= end2)
        reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];

    //然后这里是分情况,如果arr2序列的已经全部都放进reg序列了然后跳出了循环
    //那就表示arr序列还有更大的元素(一个或多个)没有放进reg序列,所以这一步就是接着放
    while (start1 <= end1)
        reg[k++] = arr[start1++];

    //这一步和上面一样
    while (start2 <= end2)
        reg[k++] = arr[start2++];
    //把已经有序的reg序列放回arr序列中
    for (k = start; k <= end; k++)
        arr[k] = reg[k];
}

void MergeSort(int arr[], const int len) {
    //创建一个同样长度的序列,用于临时存放
    int  reg[len];
    Merge(arr, reg, 0, len - 1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值