几种排序算法的比较

本文介绍了7种常见的排序算法:选择排序、快速排序、冒泡排序、插入排序、希尔排序、归并排序和堆排序。详细阐述了每种排序算法的思想,并提到了它们的时间复杂度比较,帮助理解各种排序算法的优缺点。
摘要由CSDN通过智能技术生成

1.选择排序
思想:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

void selectionsort(int a[],int n)
{
       for(int i=0;i<=n-1;i++)
       {
           int min=a[i];
           int min_index=i;
           for(int j=i;j<=n-1;j++)
           {
               if(a[j]<min)
               {
                  min=a[j];
                  min_index=j;
               }
            }
            if(min_index!=i)
            {
                swap(a[i],a[min_index]);
            }
       }
  }

2.快速排序
思想:通过一趟扫描将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列


void quicksort(int a[],int low,int high)
{
     if(low>=high)
        return;
     int i=low;
     int j=high;
     int key=a[i];
     while(i<j)//key自动覆盖数组的第一个数据
     {
     //从右向左搜索,直到搜索到的数大于等于开始记录的数,交换其位置
        while(i<j&&a[j]>=key)
          j--;
        if(i<j)
           a[i]=a[j];
           //从左向右搜索,直到搜索到的数小于等于开始记录的数,交换其位置
        while(i<j&&a[i]<=key)
          i++;
        if(i<j)
           a[j]=a[i];
      }
      a[i]=key;
      quicksort(a,low,i-1);
      quicksort(a,i+1,high);
  }

3.冒泡排序
思想:用二重循环实现,外循环变量设为i,内循环变量设为j,对所有相邻记录的关键字值进行比效,如果a[j]>a[j+1],则将其交换,最终达到有序化

void Bubblesort(int a[],int n)
{
   for(int i=0;i<n-1;i++)
   {
     for(int j=0;j<n-i-1;j++)
     {
        if(a[j]>a[j+1]
        {
           swap(a[j],a[j+1]);
        }
     }
   }
 }

4.插入排序
思想:将整个数组a分为有序和无序的两个部分。前者在左边,后者在右边。开始有序的部分只有a[0] , 其余都属于无序的部分。每次取出无序部分的第一个(最左边)元素,把它加入有序部分。假设插入合适的位置p,则原p位置及其后面的有序部分元素都向右移动一个位置,有序的部分即增加了一个元素。一直做下去,直到无序的部分没有元素。

void insertionsort(int a[],int n)
{
   for(int i=1;i<size;i++)
   {
   //a[i]是最左边的无序元素,每次循环将a[i]放到合适位置 
      for(int j=0;j<i;j++)
      {
         if(a[j]>a[i])
            {
              //要把a[i]放到位置j,原下标j到i-1的元素都往后移一位 
              int temp=a[i];
              for(int k=i;k>j;k--)
                 a[k]=a[k-1];
              a[j]=temp;
              break;
            }
       }
  }

5.希尔排序
思想:希尔排序(Shell Sort)又称为“缩小增量排序”。先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。

void shsort(int a[],int n)
{
   int i,j,d;
   d=n/2;/*确定固定增虽值*/
   while(d>=1)
   {
      for(i=d+1;i<=n;i++)/*数组下标从d+1开始进行直接插入排序*/
      {
         a[0]=a[i];/*设置监视哨*/
         j=i-d; /*确定要进行比较的元素的最右边位置*/
         while((j>0)&&(a[0]<a[j]))
         {
            a[j+d]=a[j];/*数据右移*/
            j=j-d; /*向左移d个位置V*/
         }
         a[j+d]=a[0]; /*在确定的位罝插入s[i]*/
      }
      d=d/2; /*增里变为原来的一半*/
     }
    return 0;
   }
 }

6.归并排序
思想:归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。

#include<iostream>
using namespace std; 
void merge(int a[], int start, int mid, int end)
{   
     int *tmp = (int *)malloc((end-start+1)*sizeof(int));    
     int i = start;       
     int j = mid + 1;         
     int k = 0;
     while(i <= mid && j <= end)    
     {        
         if (a[i] <= a[j])           
          tmp[k++] = a[i++];       
          else            
           tmp[k++] = a[j++];   
      }    
      while(i <= mid)       
       tmp[k++] = a[i++];    
        while(j <= end)        
        tmp[k++] = a[j++];     
        for (i = 0; i < k; i++)        
        a[start + i] = tmp[i];     
        free(tmp);
};
void mergeSort(int a[], int start, int end)
{    
      if(a==NULL || start >= end)        
      return ;     
      int mid = (end + start)/2;     
      mergeSort(a, start, mid);    
       mergeSort(a, mid+1, end);     
       merge(a, start, mid, end);
 };

7.堆排序
思想:堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

void Heap_build(int a[],int root,int length)
{
    int lchild = root*2+1;//根节点的左子结点下标
    if (lchild < length)//左子结点下标不能超出数组的长度
    {
        int flag = lchild;//flag保存左右节点中最大值的下标
        int rchild = lchild+1;//根节点的右子结点下标
        if (rchild < length)//右子结点下标不能超出数组的长度(如果有的话)
        {
            if (a[rchild] > a[flag])//找出左右子结点中的最大值
            {
                flag = rchild;
            }
        }
        if (a[root] < a[flag])
        {
            //交换父结点和比父结点大的最大子节点
            swap(a[root],a[flag]);
            //从此次最大子节点的那个位置开始递归建堆
            Heap_build(a,flag,length);
        }
    }
}
 
void Heap_sort(int a[],int len)
{
    for (int i = len/2; i >= 0; --i)//从最后一个非叶子节点的父结点开始建堆
    {
        Heap_build(a,i,len);
    }
 
    for (int j = len-1; j > 0; --j)//j表示数组此时的长度,因为len长度已经建过了,从len-1开始
    {
        swap(a[0],a[j]);//交换首尾元素,将最大值交换到数组的最后位置保存
        Heap_build(a,0,j);//去除最后位置的元素重新建堆,此处j表示数组的长度,最后一个位置下标变为len-2
    }
 
}

几种算法的时间复杂度比较
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值