各排序算法及其时间复杂度比较

news/2025/1/15 17:13:58/文章来源:https://www.cnblogs.com/zkbklink/p/18403133

排序算法及其时间复杂度比较

在C语言中,排序算法是常见的算法之一,用于将一组数据按照一定顺序排列。下面我将简要介绍几种常见排序算法的时间复杂度,并给出每种排序算法的C语言代码示例。

1. 插入排序(Insertion Sort)

时间复杂度

  • 平均和最坏情况:O(n^2)
  • 最好情况:O(n)(当输入数组已经排序时)

代码示例

#include <stdio.h>  void printArray(int arr[], int size) {  int i;  for (i = 0; i < size; i++)  printf("%d ", arr[i]);  printf("\n");  
}  void insertionSort(int arr[], int n) {  int i, key, j;  for (i = 1; i < n; i++) {  key = arr[i];  j = i - 1;  /* 将arr[i]插入到已排序的序列arr[0..i-1]中的正确位置 */  while (j >= 0 && arr[j] > key) {  arr[j + 1] = arr[j];  j = j - 1;  }  arr[j + 1] = key;  printArray(arr, n);}  
}  // 测试代码  
int main() {  int arr[] = {12, 11, 13, 5, 6};  int n = sizeof(arr) / sizeof(arr[0]);  insertionSort(arr, n);  printf("Sorted array: \n");  for (int i = 0; i < n; i++)  printf("%d ", arr[i]);  printf("\n");  return 0;  
}

2. 选择排序(Selection Sort)

时间复杂度

  • 平均、最好、最坏情况:O(n^2)

代码示例

#include <stdio.h>  void printArray(int arr[], int size) {  int i;  for (i = 0; i < size; i++)  printf("%d ", arr[i]);  printf("\n");  
}  void selectionSort(int arr[], int n) {  int i, j, min_idx, temp;  for (i = 0; i < n-1; i++) {  // 寻找[i, n-1]区间的最小值的索引下标  min_idx = i;  for (j = i+1; j < n; j++)  if (arr[j] < arr[min_idx])  min_idx = j;  // 交换找到的最小元素与第i个元素  temp = arr[min_idx];  arr[min_idx] = arr[i];  arr[i] = temp;printArray(arr, n);}  
}  // 测试代码  
int main() {  int arr[] = {12, 11, 13, 5, 6,7,8};  int n = sizeof(arr) / sizeof(arr[0]);  selectionSort(arr, n);  printf("Sorted array: \n");  for (int i = 0; i < n; i++)  printf("%d ", arr[i]);  printf("\n");  return 0;  
}

3. 冒泡排序(Bubble Sort)

时间复杂度

  • 平均和最坏情况:O(n^2)
  • 最好情况:O(n)(当输入数组已经排序时)

代码示例

#include <stdio.h>  void printArray(int arr[], int size) {  int i;  for (i = 0; i < size; i++)  printf("%d ", arr[i]);  printf("\n");  
}  void bubbleSort(int arr[], int n) {  int i, j, temp;  for (i = 0; i < n-1; i++) {  for (j = 0; j < n-i-1; j++) {  if (arr[j] > arr[j+1]) {  temp = arr[j];  arr[j] = arr[j+1];  arr[j+1] = temp;  }  }printArray(arr, n);}}  // 测试代码  
int main() {  int arr[] = {10, 14, 11, 5, 6,7,8};  int n = sizeof(arr) / sizeof(arr[0]);  bubbleSort(arr, n);  printf("Sorted array: \n");  for (int i = 0; i < n; i++)  printf("%d ", arr[i]);  printf("\n");  return 0;  
}

4. 希尔排序(Shell Sort)

时间复杂度

  • 平均:取决于增量序列,O(nlogn)到O(n^2)
  • 最坏情况:O(n^s),其中s是所选用的增量序列中最大的增量

代码示例(使用简单的增量序列):

#include <stdio.h>  void printArray(int arr[], int size) {  int i;  for (i = 0; i < size; i++)  printf("%d ", arr[i]);  printf("\n");  
}  void shellSort(int arr[], int n) {  for (int gap = n/2; gap > 0; gap /= 2) {  for (int i = gap; i < n; i += 1) {  int temp = arr[i];  int j;  for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {  arr[j] = arr[j - gap];  }  arr[j] = temp;  }  printArray(arr, n);}  
}  // 测试代码  
int main() {  int arr[] = {11, 13, 12, 1, 3,9,8};  int n = sizeof(arr) / sizeof(arr[0]);  shellSort(arr, n);  printf("Sorted array: \n");  for (int i = 0; i < n; i++)  printf("%d ", arr[i]);  printf("\n");  return 0;  
}

5. 快速排序(Quick Sort)

时间复杂度

  • 平均:O(n log n)
  • 最好情况:O(n log n)
  • 最坏情况:O(n^2)(当输入数组已经排序时)

代码示例(使用递归):

#include <stdio.h>  void swap(int *xp, int *yp) {  int temp = *xp;  *xp = *yp;  *yp = temp;  
}  int partition(int arr[], int low, int high) {  int pivot = arr[high];    // 选择最后一个元素作为基准  int i = (low - 1);        // 较小元素的索引  for (int j = low; j <= high - 1; j++) {  // 如果当前元素小于或等于基准  if (arr[j] <= pivot) {  i++;    // 增加较小元素的索引  swap(&arr[i], &arr[j]);  }  }  swap(&arr[i + 1], &arr[high]);  return (i + 1);  
}  void quickSort(int arr[], int low, int high) {  if (low < high) {  /* pi 是分区后基准的正确位置 */  int pi = partition(arr, low, high);  // 递归地对基准前后的子数组进行排序  quickSort(arr, low, pi - 1);  quickSort(arr, pi + 1, high);  }  
}  // 实用函数,用于打印数组  
void printArray(int arr[], int size) {  int i;  for (i = 0; i < size; i++)  printf("%d ", arr[i]);  printf("\n");  
}  // 测试快速排序  
int main() {  int arr[] = {10, 7, 8, 9, 1, 5};  int n = sizeof(arr) / sizeof(arr[0]);  quickSort(arr, 0, n - 1);  printf("Sorted array: \n");  printArray(arr, n);  return 0;  
}

6. 归并排序(Merge Sort)

时间复杂度

  • 平均、最好、最坏情况:O(n log n)

代码示例(使用递归):

#include <stdio.h>  
#include <stdlib.h>  void merge(int arr[], int l, int m, int r) {  int i, j, k;  int n1 = m - l + 1;  int n2 = r - m;  // 创建临时数组  int L[n1], R[n2];  // 拷贝数据到临时数组  for (i = 0; i < n1; i++)  L[i] = arr[l + i];  for (j = 0; j < n2; j++)  R[j] = arr[m + 1 + j];  // 合并临时数组回到原数组arr[l..r]  i = 0; // 初始索引第一个子数组  j = 0; // 初始索引第二个子数组  k = l; // 初始索引被合并的子数组  while (i < n1 && j < n2) {  if (L[i] <= R[j]) {  arr[k] = L[i];  i++;  } else {  arr[k] = R[j];  j++;  }  k++;  }  // 拷贝L[]的剩余元素  while (i < n1) {  arr[k] = L[i];  i++;  k++;  }  // 拷贝R[]的剩余元素  while (j < n2) {  arr[k] = R[j];  j++;  k++;  }  
}  void mergeSort(int arr[], int l, int r) {  if (l < r) {  // 找到中间点  int m = l + (r - l) / 2;  // 分别对左右子数组进行排序  mergeSort(arr, l, m);  mergeSort(arr, m + 1, r);  // 合并两个已排序的子数组  merge(arr, l, m, r);  }  
}  // 实用函数,用于打印数组  
void printArray(int arr[], int size) {  int i;  for (i = 0; i < size; i++)  printf("%d ", arr[i]);  printf("\n");  
}  // 测试归并排序  
int main() {  int arr[] = {12, 11, 13, 5, 6, 7};  int arr_size = sizeof(arr) / sizeof(arr[0]);  printf("Given array is \n");  printArray(arr, arr_size);  mergeSort(arr, 0, arr_size - 1);  printf("\nSorted array is \n");  printArray(arr, arr_size);  return 0;  
}

在上述的几种排序算法中,各排序算法在各种情况中,运行时间的快慢都不一样,而在其中相较于一般情况,归并列算法相当于有不错的表现,而对于各时间复杂度下的快慢,本人列了一张表格,由快到慢(表格由上至下)如图表所示,所以在不同的数据处理场景中可以相对数据以及各硬件速度选择不同的排序算法,以达到程序的最优解。

理解和分析算法的时间复杂度是算法设计、优化和选择中的重要环节。通过比较不同算法的时间复杂度,我们可以评估它们在处理大规模数据时的效率和可行性。

名称 时间复杂度
常数时间 O(1)
对数时间 O( log n)
线性时间 O(n )
线性对数时间 O(n log n)
二次时间 O(n^2)
三次时间 O(n^3)
指数时间 O(2^n)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/794076.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

51nod 石子分配

可以发现步数限制把数轴变为了环。环之间不可以交换,环内相邻两点可以交换,然后我们只需要对每个环操作,最后累加。 对于环上的每个石子堆,我们需要将其石子数调整到均值 \(avg\)。因此,我们首先计算每个堆石子相对于 \(avg\) 的偏差,即 \(nowa[i] - avg\)。 因为相邻节点…

马哥教育C10网络安全课第四周作业2024_0831

网络安全C10-2024.8.31 作业: 1、安装burp并实现抓取HTTP站点的数据包(HTTPS站点暂时不要求) (1)安装Java 1.8.144; 设定操作系统环境变量 - JAVA_HOME jdk文件夹的绝对路径 例: JAVA_HOME=C:\Program Files\Java\jdk1.8.0_144 - CLASSPATH CLASSJPATH=.;%JAVA_HOME%\lib…

十年来(2015-2024)植物/农学领域有哪些学者戴上了杰青帽子?

2024年杰青建****议资助项目申请人名单(部分名单)(注:该表只是统计现公布的名单,欢迎留言补充) 2023年杰青建议资助项目申请人名单2022年杰青建议资助项目申请人名单2020年杰青建议资助项目申请人名单2019杰青建议资助项目申请人名单2018杰青建议资助项目申请人名单2017杰…

Nature Comm. | CoPheScan:一种考虑连锁不平衡的全表型组关联分析

分享一篇最近发表在NC的一篇文章:CoPheScan: phenome-wide association studies accounting for linkage disequilibrium。文章介绍了一种新的贝叶斯方法CoPheScan(Coloc adapted Phenome-wide Scan),用于在考虑连锁不平衡(LD)的情况下进行表型范围关联研究(Phenome-wid…

智能农业和精准农业中的计算机视觉:技术与应用

计算机视觉智能系统融合了计算机视觉、人工智能和机器学习技术,使机器能够模仿人类的视觉和认知能力做出决策,已广泛融入现代人类生活的各个层面。自 20 世纪后期以来,自动化的视觉系统已革新了各多个行业。鉴于世界人口的增长、可耕地的减少以及劳动力的短缺等问题,农业从…

Plant Com | 上海师范大学生科院解析杂草稻近代野化的进化机制

2024年8月19日,上海师范大学生命科学学院的研究团队在_Plant Communications在线发表了题为“Landrace introgression contributed to the recent feralization of weedy rice in East China”的论文。研究揭示了我国江浙沪地区稻田中的杂草稻都为近代野化起源,并均衍生于籼型…

PBJ | 钱前院士综述:野生稻——开启水稻育种的未来

PBJ近日在线发表了中国农业科学院和崖州湾国家实验室合作的题为“Wild rice: unlocking the future of rice breeding”的综述论文,文章系统梳理了稻属各物种间的系统进化关系、分类及地理分布,栽培稻育种中已鉴定的野生稻来源基因,分析了野生稻耐生物胁迫、非生物胁迫基因的…

图解:14个国家超级计算中心

相信大家都听过计算机、数据中心,超级计算机,但是超级计算中心是什么呢?听起来不明觉厉,但其实超级计算中心就是将多个超级计算机放在一个数据中心内。国家超级计算中心是由国家科技部批准成立的数据计算机构,是科技部下属事业单位。那么超级计算中心有什么作用呢?当然是…

综述 | 杂种优势形成机制和预测方法及其在猪生产中的应用与展望

杂种优势是指不同品种或品系间的杂交代在生长、发育、繁殖和抗病抗逆等性状优于亲代的现象。杂交能有效提高后代的生长发育性能、繁殖性能和抗病性,因此被广泛应用于农业生产。然而,现有杂种优势理论只能解释部分杂种优势现象;并且由于杂种优势理论不完善,现有的杂种优势预…

全球7大家禽育种公司的前世今生

我国白羽肉鸡的祖代全部是从国外引进的品种,属于快大型肉鸡,其生长速度快、产肉量多,适合工业化生产,作为肉鸡屠宰加工企业的主要原料,白羽肉鸡是我国肉鸡产品主导品种,目前我国白羽肉鸡主要包括艾拔益加(AA+)、罗斯(Ross)308、科宝(Cobb)、海波罗(Hybro)和哈伯德…

中国农作物分布地图(2015-2021年)

中国是世界人口最多的国家,在全球谷物生产方面排名第一。通过多样化作物种类的多熟制种植,可以显著增加农作物产量,并减少相关的环境影响。全球约12%的农田实行多熟制,其中34%的水稻地采用多熟制系统。中国用仅占全球7%的耕地养活了世界20%的人口。中国约三分之一的农田种植…