几种常见排序算法
几种常见排序算法
使用语言及编译环境
- 使用语言:C/C++
- 编译环境:VS Code
冒泡排序
参照https://www.bilibili.com/video/BV1T4411A7Fy?p=7
- 原理:数组元素两两比较,交换元素,大元素往后放
#include <iostream> using namespace std; int main() { int arrayLength = 6; int array[arrayLength] = {10,2,5,80,35,60}; for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; for (size_t i = 0; i < arrayLength-1; i++) { for (size_t j = 0; j < arrayLength-1-i; j++) { if (array[j] > array[j+1]) { int temp = array[j+1]; array[j+1] = array[j]; array[j] = temp; } } } for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; system("pause"); return 0; }
选择排序
参照https://www.bilibili.com/video/BV1T4411A7Fy?p=8
- 原理:从0索引处开始,将该位置的元素依次和后面的元素进行比较,小的元素往前放
#include <iostream> using namespace std; int main() { int arrayLength = 6; int array[arrayLength] = {10,2,5,80,35,60}; for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; for (size_t index = 0; index < arrayLength-1; index++) { for (size_t i = index+1; i < arrayLength; i++) { if (array[index] > array[i]) { int temp = array[index]; array[index] = array[i]; array[i] = temp; } } } for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; system("pause"); return 0; }
直接插入排序
参照https://www.bilibili.com/video/BV1T4411A7Fy?p=9
- 原理:从1索引处开始,将后面的元素插入之前的有序列表中,使之仍保持有序
#include <iostream> using namespace std; int main() { int arrayLength = 6; int array[arrayLength] = {10,2,5,80,35,60}; for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; for (size_t i = 1; i < arrayLength; i++) { for (size_t j = i; j > 0; j--) { if (array[j] < array[j-1]) { int temp = array[j]; array[j] = array[j-1]; array[j-1] = temp; } } } for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; system("pause"); return 0; }
希尔排序
参照https://www.bilibili.com/video/BV1T4411A7Fy?p=10
- 原理:合理选取增量,一轮排序后,不断缩小增量进行插入排序,直到增量为1,排序就结束
- 直接插入排序相当于增量为1的希尔排序
- 增量的合理选择:克努特(Knuth)序列导入,h=3*h+1
#include <iostream> using namespace std; int main() { int arrayLength = 6; int array[arrayLength] = {10,2,5,80,35,60}; for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; //克努特序列选取增量 int spac = 1; while (spac <= arrayLength/3) { spac = spac*3+1; } //cout << "spac: " << spac << endl; for (size_t h = spac; h > 0; h=(h-1)/3) { for (size_t i = h; i < arrayLength; i++) { for (size_t j = i; j > h-1; j-=h) { if (array[j] < array[j-h]) { int temp = array[j]; array[j] = array[j-h]; array[j-h] = temp; } } } } for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; system("pause"); return 0; }
快速排序
参照https://www.bilibili.com/video/BV1at411T75o/?spm_id_from=333.788
- 思想:分治法,比大小,在分区
- 原理:从数组中取一个数,将比这个数大的全放到右边,比这个数小的全放到左边;对左右两个分区进行此步骤,直到最后分区只有一个数
- 步骤:选一个基准数,先从后往前找小于它的数,将这个数放到基准数的位置,然后在从前往后找大于等于它的数,将这个数放到上一个小于基准数的位置,直到左右两个寻找的指针重合,然后重复对左区和右区进行上述操作,直到分区只有一个元素的时候,就认为整个数组有序了
#include <iostream> using namespace std; void quickSort(int *arr, int start, int end); int main() { int arrayLength = 6; int array[arrayLength] = {10,2,5,80,35,60}; for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; quickSort(array, 0, arrayLength-1); for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; system("pause"); return 0; } void quickSort(int *arr, int start, int end) { if (start>=end) { return; } int L = start; int R = end; int pivot = arr[L]; while (L<R) { //由后往前找比它小的数 while (L<R && arr[R]>=pivot) { R--; } if (L<R) { arr[L] = arr[R]; L++; } //由前往后找比它大或者等于的数 while (L<R && arr[L]<pivot) { L++; } if (L<R) { arr[R] = arr[L]; R--; } //把基准数放到最后L和R重合的地方 if (L>=R) { arr[L] = pivot; } } //递归处理左区和右区 quickSort(arr, start, L-1); quickSort(arr, L+1, end); }
归并排序
参照:https://www.bilibili.com/video/BV1Pt4y197VZ?spm_id_from=333.337.search-card.all.click
- 思想:先划分再合并
- 原理:将数组中每个元素分为一组,然后两两组合,保证每次组合出来的数组都是有序的,直到只剩下一组的时候,排序完成
#include <iostream> using namespace std; void mergeSort(int *arr, int size); int main() { int arrayLength = 6; int array[arrayLength] = {10,2,5,80,35,60}; for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; mergeSort(array, arrayLength); for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; system("pause"); return 0; } //合并 void merge(int *arr, int *tempArr, int left, int mid, int right) { int l = left; //标记左半区第一个未排序元素 int r = mid+1;//标记右半区第一个未排序元素 int t_pos = left;//临时数组的下标 //合并 while ((l <= mid)&&(r <= right)) { if (arr[l] <= arr[r]) { tempArr[t_pos++] = arr[l++]; } else { tempArr[t_pos++] = arr[r++]; } } //合并左半区剩余的元素 while (l <= mid) { tempArr[t_pos++] = arr[l++]; } //合并右半区剩余的元素 while (r <= right) { tempArr[t_pos++] = arr[r++]; } //把临时数组的元素放入原数组 while (left <= right) { arr[left] = tempArr[left]; left++; } } //归并排序 void mSort(int *arr, int *tempArr, int left, int right) { if (left<right) { int mid = (left+right)/2; mSort(arr, tempArr, left, mid); //递归划分左半区域 mSort(arr, tempArr, mid+1, right); //递归划分右半区域 merge(arr, tempArr, left, mid, right); //合并部分 } return; } //入口函数 void mergeSort(int *arr, int size) { int *tempArr = new int[sizeof(int)*size]; if (tempArr != NULL) { mSort(arr, tempArr, 0, size-1); delete []tempArr; } return; }
基数排序
- 原理:先分配再收集
- 步骤:按个位数的大小从小到大分配,然后把数据顺序收集起来;把上一步数据按十位数的大小从小到大分配,然后把数据顺序收集起来……依次类推,你数据有多少位,就收集分配几次
#include <iostream> using namespace std; int Max(int arr[], size_t size); int main() { int arrayLength = 6; int array[arrayLength] = {10,2,5,80,35,60}; for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; //二维数组用来分配数据 int tempArr[10][arrayLength]; //统计数组用来标记二维数组每个tempArr[index][]有多少个元素 int count[10] = {0}; //确定排序轮次 int max = Max(array, arrayLength); int rounds = 0; //cout << "max: " << max << endl; while ( max!=0 ) { max = max/10; rounds++; } //cout << "rounds: " << rounds << endl; for (size_t i = 0, n = 1; i < rounds; i++, n*=10) { for (size_t j = 0; j < arrayLength; j++) { //确定每个位上的数据 int number = array[j]/n%10; //分配数据 tempArr[number][count[number]++] = array[j]; } //收集二位数组里面的元素 int index = 0; for (size_t k = 0; k < 10; k++) { if (count[k] != 0) { for (size_t h = 0; h < count[k]; h++) { array[index++] = tempArr[k][h]; } count[k] = 0;//拿完元素后将标记值变为0 } } } for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; return 0; } int Max(int arr[], size_t size) { int max = arr[0]; for (size_t i = 1; i < size; i++) { max = max>arr[i]?max:arr[i]; } return max; }
堆排序
参照:https://www.bilibili.com/video/BV1T4411A7Fy?p=14&spm_id_from=pageDriver
- 基础概念:
- 大顶堆:所有根节点大于两个字节点
- 小顶堆:所有根节点小于两个字节点
- 步骤:
- 将数组看做一个完全二叉树
- 将完全二叉树构造为一个大顶堆
- 将根节点与末尾元素交换
- 将剩余n-1个元素重复上述两个步骤,直到最后一个元素后这个序列便有序了
#include <iostream> using namespace std; void toMaxHeap(int arr[], int size, int index); int main() { int arrayLength = 6; int array[arrayLength] = {10,2,5,80,35,60}; for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; //定义开始调整的位置 int startIndex = (arrayLength-2)/2; //循环调整,将数组变成一个大顶堆 for (int i = startIndex; i >= 0; i--) { toMaxHeap(array, arrayLength, i); } for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; //把根元素和最后一个元素调换 for (int i = arrayLength-1; i >= 0; i--) { int temp = array[0]; array[0] = array[i]; array[i] = temp; //换完再把剩余元素调成大顶堆 toMaxHeap(array, i, 0); } for (int i = 0; i < arrayLength; i++) { cout << array[i] << " "; } cout << endl; return 0; } void toMaxHeap(int arr[], int size, int index) { if (index >= size) { return; } //获取左右字节点的索引 int leftNodeIndex = index*2+1; int rightNodeIndex = index*2+2; int maxIndex = index; //查找最大节点对应的索引 if (leftNodeIndex<size && arr[leftNodeIndex]>arr[maxIndex]) { maxIndex = leftNodeIndex; } if (rightNodeIndex<size && arr[rightNodeIndex]>arr[maxIndex]) { maxIndex = rightNodeIndex; } //调换位置 if (maxIndex != index) { int temp = arr[maxIndex]; arr[maxIndex] = arr[index]; arr[index] = temp; //调完位置后可能会影响到后面的树不是大顶堆 toMaxHeap(arr, size, maxIndex); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?