排序算法大集合---(冒泡,选择,插入,快速,归并,堆排序)

本文深入讲解了冒泡排序、选择排序、插入排序等经典排序算法的基本思想、时间复杂度及稳定性,并提供了详细的代码实现,是理解和掌握排序算法原理的宝贵资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

冒泡排序

 基本思想:

通过比较相邻两个元素的大小进行互换排序

每趟排序至少有一个元素处在正确的位置上

平均时间复杂度O(n^20),空间复杂度O(1),稳定 

 代码实现:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100+5;
int a[maxn];
int n;
void BubbleSort(int *a){
  for(int i=0;i<n;i++){
    for(int j=0;j<i;j++){
      if(a[j]>a[j+1]) swap(a[j],a[j+1]);
    }
  }
}

选择排序

 基本思想:

  从第一个元素开始依次与其后的元素作比较

  每一趟在n-i+1(i=0,1,2,···n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录

  平均时间复杂度O(n^2),空间复杂度O(1),不稳定

 代码实现:  

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

插入排序:针对有序序列

 直接插入排序

  基本思想:

从第二个元素位置逐个开始插入

每插入一个元素得到的序列均为有序序列

平均时间复杂度O(n^2),空间复杂度O(1),稳定

  代码实现:

void StraightInsertSort(int *a){
  for(int i=1;i<n;i++){
    int temp=a[i];
    int j=0;
    for(j=i;j>0;j--){
      if(a[j-1]>temp){    //元素后移
        a[j]=a[j-1];
      }
      else break;
    }
    a[j]=temp;
  }
}

 希尔排序

   基本思想:

  又名缩小增量排序,一种优化的插入排序

  先将序列分割,分别直接插入排序,最后对全体直接插入排序

  平均时间复杂度O(n^1.3),空间复杂度O(1),不稳定

   代码实现:

void ShellSort(int *a){
  int h=1;
  while(h<n/3){        //确定增量范围公式
    h=h*3+1;                  
  }
  while(h>=1){
    for(int i=h;i<n;i++){
      int temp=a[i];
      int j=0;
      for(j=i;j<n&&a[j-h]>temp;j-=h){
        a[j]=a[j-h];   //元素后移      
      }
      a[j]=temp;       //找到插入位置
    }
    h/=3;
  }
}

二分插入排序

 基本思想:

每次通过折半查找确定目标元素的插入位置,一定程度上减少元素移动次数

确定好插入位置后,只需依次实现元素后移

平均时间复杂度O(n^2),空间复杂度O(1),稳定

 代码实现: 

int binarySerach(int *a,int i){  //寻找插入位置
  int lowindex=0;
  int highindex=i-1;
  int mid=0;
  while(lowindex<=highindex){
    mid=(lowindex+highindex)/2;
    if(a[i]>=a[mid])
      lowindex=mid+1;
    else
      highindex=mid-1;
  }
  return lowindex;
}
void binaryInsertSort(int *a){
  for(int i=1;i<n;i++){
    int temp=a[i];
    int k=binarySerach(a,i);    //折半查找
    for(int j=i-1;j>=k;j--){    //元素后移
      a[j+1]=a[j];
    }
    a[k]=temp;                  //k为插入位置
  }
}

快速排序

 基本思想:

  通过一趟排序将原记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,再分别对两部分进行排序

  平均时间复杂度O(nlogn),空间复杂度O(nlogn),不稳定

 代码实现:

int quickSort(int *a,int low,int high){  //一趟快排
  //low=0,high=n-1;
  int temp=a[low];  //基准数据
  while(low<high){
    while(temp<=a[high]&&low<high)  //当基准数据小于后面的元素时,右值索引-1
      --high;
    a[low]=a[high];                 //不然移动后面的元素到前面
    while(temp>=a[low]&&low<high)   //当基准数据大于前面的元素时,左值索引+1
      ++low;
    a[high]=a[low];                 //不然移动前面的元素到后面
  }
  a[low]=temp;                      //确定基准数据位置
  return low;
}
void QuickSort(int *a,int low,int high){
  int key=0;
  if(low<high){
    key=quickSort(a,low,high);
    //分别对每一部分快排
    quickSort(a,low,key-1);
    quickSort(a,key+1,high);
  }
}

归并排序

 基本思想:

将两个以上的有序序列合并为一个有序序列,为多路归并排序

平均时间复杂度O(nlogn),空间复杂度O(n),稳定

 代码实现:

void merge(int *a,int first,int mid,int last){  //合并两个有序序列
  int temp[n];  //开辟临时数组
  int i=first,j=mid+1;
  int m=mid,n=last;
  int k=0;
  //填充临时数组
  while(i<=m&&j<=n){
    if(a[i]<=a[j])
      temp[k++]=a[i++];
    else
      temp[k++]=a[j++];
  }
  //将a中剩余的元素依次放进临时数组中
  while(i<=m) temp[k++]=a[i++];
  while(j<=n) temp[k++]=a[j++];
  for(int i=0;i<k;i++){
    a[first+i]=temp[i];
  }
}
void mergeSort(int *a,int first,int last){
  if(first<last){
    int mid=(first+last)/2;
    mergeSort(a,first,mid);
    mergeSort(a,mid+1,last);
    merge(a,first,mid,last);
  }
}

 堆排序

  基本思想:

  根据原数组建立初始堆进而调整形成大(小)根堆,最后通过层序遍历实现对数组关键字的排序

  只要一个记录大小的辅助空间,每个待排序记录仅占有一个存储空间

  平均时间复杂度O(nlogn),空间复杂度O(1),不稳定

  代码实现:

void maxHeapDown(int *a,int start,int end){  //大根堆,初始堆为元素按层次插入形成的
  int c=start;  //当前节点位置
  int l=2*c+1;  //左孩子位置
  int temp=a[c];
  for(;l<=end;c=l,l=2*l+1){
    if(l<end&&a[l]<a[l+1])  //寻找左右孩子中的较大值
      l++;
    //确保当前节点为最大值
    if(temp>=a[l])
      break;
    else{
      a[c]=a[l];a[l]=temp;
    }
  }
}
void heapSortAsc(int *a,int n){              //升序
  for(int i=n/2-1;i>=0;i--){
    maxHeapDown(a,i,n-1);  //得到最大二叉堆
  }
  for(int i=n-1;i>0;i--){
    swap(a[0],a[i]);       //交换后,a[i]是a[0...i]中最大的
    maxHeapDown(a,0,i-1);  //调整a[0...i-1],使得a[0...i-1]仍然是一个最大堆
  }
}
void minHeapDown(int *a,int start,int end){  //小根堆
  int c=start;
  int l=2*c+1;
  int temp=a[c];
  for(;l<=end;c=l,l=2*l+1){
    if(l<end&&a[l]>a[l+1])
      l++;
    if(temp<=a[l])
      break;
    else{
      a[c]=a[l];a[l]=temp;
    }
  }
}
void heapSortDesc(int *a,int n){             //降序
  for(int i=n/2-1;i>=0;i--){
    minHeapDown(a,i,n-1);
  }
  for(int i=n-1;i>0;i--){
    swap(a[0],a[i]);
    minHeapDown(a,0,i-1);
  }
}

 主函数实现:

int main(){
  cin>>n;
  for(int i=0;i<n;i++)
    scanf("%d",&a[i]);
  //BubbleSort(a);
  //SelectSort(a);
  //StraightInsertSort(a);
  //binaryInsertSort(a);
  //ShellSort(a);
  //QuickSort(a,0,n-1);
  //heapSortAsc(a,n);
  //mergeSort(a,0,n-1);
  for(int i=0;i<n;i++){
    if(i<n-1) printf("%d ",a[i]);
    else printf("%d\n",a[i]);
  }
  return 0;
}

代码均已正确验证过

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值