七大排序完整版
目录
一、直接插入排序
(一)单趟直接插入排
1.分析+核心代码
2.完整代码
(二)全部直接插入排
1.分析+核心代码
2.完整代码
(三)时间复杂度和空间复杂度
二、希尔排序
(一)对一组数据进行直接插入排序
(二)对每个分组分别进行直接插入排序
(三)对每个分组同时进行直接插入排序
(四)可变的gap
(五)时间复杂度和空间复杂度
三、直接选择排序
(一)找一个最小值
1、单趟直接选择排序
2、多趟选择排序
3、时间复杂度和空间复杂度
(二)同时找最小值和最大值
1、单趟直接选择排序
2、多趟选择排序
3、时间复杂度和空间复杂度
四、冒泡排序
(一)核心代码
(二)完整代码
(三)时间复杂度
五、快速排序
(一)Hoare
1. 易出错分析——死循环
2. 易出错分析——越界
3. 一次快排核心代码
4. 递归核心代码
5. 测试代码
6. 时间复杂度
(二)挖坑法
1. 单趟挖坑的代码
2. 单趟测试代码
3. 递归挖坑代码
4. 递归挖坑测试代码
(三)前后指针
1. 单趟核心代码
2. 单趟测试代码
3. 递归核心代码
4. 递归测试代码
(四)非递归实现(栈)
六、归并排序
1. 递归核心代码
2. 测试代码
3. 非递归核心代码
4. 测试代码
七、堆排序
1. 向下调整
2. 建堆
3. 堆排序代码
4. 向上调整
5. 测试
一、直接插入排序
(一)单趟直接插入排
1.分析+核心代码

void InsertSort(int* data, int n)
{//[0,end]有序int end = n - 2;int tmp = data[end+1];while (end >= 0)//升序{if (data[end] > tmp){data[end + 1] = data[end];--end;}else{break;}}data[end + 1] = tmp;
}
2.完整代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void InsertSort(int* data, int n)
{//[0,end]有序int end = n - 2;int tmp = data[end+1];while (end >= 0)//升序{if (data[end] > tmp){data[end + 1] = data[end];--end;}else{break;}}data[end + 1] = tmp;
}
void Print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}
}
int main()
{int a[] = { 1,6,10,12,13,7 };InsertSort(a, sizeof(a) / sizeof(int));Print(a, sizeof(a) / sizeof(int));return 0;
}
(二)全部直接插入排
1.分析+核心代码
- 红色线条前的数据依次和tmp比较,比tmp大就往后面挪动

void InsertSort(int* data, int n)
{for (int i = 0; i < n-1; i++){int end = i;int tmp = data[end+1];while (end >= 0)//升序{if (data[end] > tmp){data[end + 1] = data[end];--end;}else{break;}}data[end + 1] = tmp;}
}
2.完整代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void InsertSort(int* data, int n)
{for (int i = 0; i < n-1; i++){int end = i;int tmp = data[end+1];while (end >= 0)//升序{if (data[end] > tmp){data[end + 1] = data[end];--end;}else{break;}}data[end + 1] = tmp;}
}
void Print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}
}
int main()
{int a[] = { 1,6,17,12,4 };InsertSort(a, sizeof(a) / sizeof(int));Print(a, sizeof(a) / sizeof(int));return 0;
}
(三)时间复杂度和空间复杂度

二、希尔排序
(一)对一组数据进行直接插入排序


void ShellSort(int* data, int n)
{int gap = 3;for (int i = 0; i+gap < n; i+=gap)//对第一组数据进行插入排序{int end = i;int tmp = data[end + gap];while (end >= 0){if (data[end] > tmp){data[end + gap] = data[end];end = end - gap;}elsebreak;}data[end + gap] = tmp;}
}
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>
void ShellSort(int* data, int n)
{int gap = 3;for (int i = 0; i+gap < n; i+=gap)//对第一组数据进行插入排序{int end = i;int tmp = data[end + gap];while (end >= 0){if (data[end] > tmp){data[end + gap] = data[end];end = end - gap;}elsebreak;}data[end + gap] = tmp;}
}
void Print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
int main()
{int a[] = { 9,4,3,0,5,6,7,2,1,8 };ShellSort(a, sizeof(a) / sizeof(int));Print(a, sizeof(a) / sizeof(int));return 0;
}
(二)对每个分组分别进行直接插入排序


void ShellSort(int* data, int n)
{int gap = 3;for (int k = 0; k < gap; k++)//一共有gap组{for (int i = k; i + gap < n; i += gap)//对第k组数据进行插入排序{int end = i;int tmp = data[end + gap];while (end >= 0){if (data[end] > tmp){data[end + gap] = data[end];end = end - gap;}elsebreak;}data[end + gap] = tmp;}}
}
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>
void ShellSort(int* data, int n)
{int gap = 3;for (int k = 0; k < gap; k++)//一共有gap组{for (int i = k; i + gap < n; i += gap)//对第k组数据进行插入排序{int end = i;int tmp = data[end + gap];while (end >= 0){if (data[end] > tmp){data[end + gap] = data[end];end = end - gap;}elsebreak;}data[end + gap] = tmp;}}
}
void Print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
int main()
{int a[] = { 9,4,3,0,5,6,7,2,1,8 };ShellSort(a, sizeof(a) / sizeof(int));Print(a, sizeof(a) / sizeof(int));return 0;
}
(三)对每个分组同时进行直接插入排序
void ShellSort(int* data, int n)
{int gap = 3;for (int i = 0; i + gap < n; i++)//对多组同时进行直接插入排序{int end = i;int tmp = data[end + gap];while (end >= 0){if (data[end] > tmp){data[end + gap] = data[end];end = end - gap;}elsebreak;}data[end + gap] = tmp;}
}
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>
void ShellSort(int* data, int n)
{int gap = 3;for (int i = 0; i + gap < n; i++)//对多组同时进行直接插入排序{int end = i;int tmp = data[end + gap];while (end >= 0){if (data[end] > tmp){data[end + gap] = data[end];end = end - gap;}elsebreak;}data[end + gap] = tmp;}
}
void Print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
int main()
{int a[] = { 9,4,3,0,5,6,7,2,1,8 };ShellSort(a, sizeof(a) / sizeof(int));Print(a, sizeof(a) / sizeof(int));return 0;
}

(四)可变的gap
void ShellSort(int* data, int n)
{int gap = n;while (gap > 1){//1、gap > 1 与排序//2、gap == 1直接插入排序gap = gap / 3 + 1;for (int i = 0; i + gap < n; i++)//对多组同时进行直接插入排序{int end = i;int tmp = data[end + gap];while (end >= 0){if (data[end] > tmp){data[end + gap] = data[end];end = end - gap;}elsebreak;}data[end + gap] = tmp;}}
}
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>
void ShellSort(int* data, int n)
{int gap = n;while (gap > 1){//1、gap > 1 与排序//2、gap == 1直接插入排序gap = gap / 3 + 1;for (int i = 0; i + gap < n; i++)//对多组同时进行直接插入排序{int end = i;int tmp = data[end + gap];while (end >= 0){if (data[end] > tmp){data[end + gap] = data[end];end = end - gap;}elsebreak;}data[end + gap] = tmp;}}
}
void Print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
int main()
{int a[] = { 9,4,3,0,5,6,7,2,1,8 };ShellSort(a, sizeof(a) / sizeof(int));Print(a, sizeof(a) / sizeof(int));return 0;
}
(五)时间复杂度和空间复杂度

三、直接选择排序
- 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。

(一)找一个最小值
1、单趟直接选择排序
- 从待排序列中选出一个最小值,然后放在序列的起始位置
void SelectSort(int* data, int n)
{int start = 0;//待排序的数据的区间的开始位置int min_index = start;//最小元素的小标for (int i = start; i < n; i++){if (data[i] < data[min_index]){min_index = i;}}Swap(&data[start], &data[min_index]); //最小值与第一个元素交换位置
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
void SelectSort(int* data, int n)
{int start = 0;//待排序的数据的区间的开始位置int min_index = start;//最小元素的下标for (int i = start; i < n; i++){if (data[i] < data[min_index]){min_index = i;}}Swap(&data[start], &data[min_index]); //最小值与第一个元素交换位置
}
int main()
{int a[] = { 9,3,6,2,7,4 };print(a, sizeof(a) / sizeof(int));SelectSort(a, sizeof(a) / sizeof(int));print(a, sizeof(a) / sizeof(int));return 0;
}

2、多趟选择排序
void SelectSort(int* data, int n)
{for (int k = 0; k < n; k++)//某一趟选择排序从下标为k的元素开始{int start = k;//待排序的数据的区间的开始位置int min_index = start;//最小元素的下标for (int i = start; i < n; i++){if (data[i] < data[min_index]){min_index = i;}}Swap(&data[start], &data[min_index]); //最小值与参与第一个元素交换位置}
}
3、时间复杂度和空间复杂度

(二)同时找最小值和最大值
1、单趟直接选择排序
- 一趟选出两个值,一个最大值一个最小值,分别放在放在开头和结尾
void SelectSort(int* data, int n)
{int begin = 0;//待排序的数据的区间的开始位置int end = n - 1;int min_index = begin;//最小元素的下标int max_index = end;//最大元素的下标for (int i = 0; i < n; i++){if (data[i] < data[min_index]){min_index = i;}if (data[i] > data[max_index]){max_index = i;}}Swap(&data[begin], &data[min_index]); //最小值与第一个元素交换位置if (max_index == begin)//如果最大值在第一个位置处{max_index = min_index;}Swap(&data[end], &data[max_index]); //最大值和最后一个元素交换位置//下次调整[1,n-2]之间的数据
}
2、多趟选择排序
void SelectSort(int* data, int n)
{int begin = 0;//待排序的数据的区间的开始位置int end = n - 1;while (begin < end){int min_index = begin;//最小元素的下标int max_index = end;//最大元素的下标for (int i = begin; i <= end; i++){if (data[i] < data[min_index]){min_index = i;}if (data[i] > data[max_index]){max_index = i;}}Swap(&data[begin], &data[min_index]); //最小值与第一个元素交换位置if (max_index == begin)//如果最大值在第一个位置处{max_index = min_index;}Swap(&data[end], &data[max_index]); //最大值和最后一个元素交换位置//下次调整[1,n-2]之间的数据begin++;end--;}
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
void SelectSort(int* data, int n)
{int begin = 0;//待排序的数据的区间的开始位置int end = n - 1;while (begin < end){int min_index = begin;//最小元素的下标int max_index = end;//最大元素的下标for (int i = begin; i <= end; i++){if (data[i] < data[min_index]){min_index = i;}if (data[i] > data[max_index]){max_index = i;}}Swap(&data[begin], &data[min_index]); //最小值与第一个元素交换位置if (max_index == begin)//如果最大值在第一个位置处{max_index = min_index;}Swap(&data[end], &data[max_index]); //最大值和最后一个元素交换位置//下次调整[1,n-2]之间的数据begin++;end--;}
}
int main()
{int a[] = { 9,3,6,2,7,4 };print(a, sizeof(a) / sizeof(int));SelectSort(a, sizeof(a) / sizeof(int));print(a, sizeof(a) / sizeof(int));return 0;
}
3、时间复杂度和空间复杂度

四、冒泡排序
- 基本思想:从第一个元素开始,比较相邻元素的大小,若大小有误,则对调再进行下一个元素的比较,如此扫过依次之后就可以确保最后一个元素位于正确的顺序。接着进行第二次扫描

(一)核心代码
void BubbleSort(int* data, int n)
{for (int end = n - 1; end >= 0; end--)//每次将数据交换到下标为end的位置处{bool exchange = false;for (int i = 0; i < end; i++)//[i,end-1]{if (data[i] > data[i + 1]){Swap(&data[i], &data[i + 1]);exchange = true;}}if (exchange == false)break;}
}
(二)完整代码
#include<stdio.h>
#include<stdbool.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
void BubbleSort(int* data, int n)
{for (int end = n - 1; end >= 0; end--)//每次将数据交换到下标为end的位置处{bool exchange = false;for (int i = 0; i < end; i++)//[i,end-1]{if (data[i] > data[i + 1]){Swap(&data[i], &data[i + 1]);exchange = true;}}if (exchange == false)break;}
}
int main()
{int a[] = { 9,3,6,2,7,4 };//int a[] = { 1,2,3,4,5,6 };print(a, sizeof(a) / sizeof(int));BubbleSort(a, sizeof(a) / sizeof(int));print(a, sizeof(a) / sizeof(int));return 0;
}
(三)时间复杂度

五、快速排序
(一)Hoare

1. 易出错分析——死循环


2. 易出错分析——越界


3. 一次快排核心代码
int PartSort(int* data, int begin, int end)
{int key_index = begin;int left = begin;int right = end;while (left < right){//右边先走while (left < right && data[right] >= data[key_index])//右边找小{--right;}while (left < right && data[left] <= data[key_index])//左边找大{++left;}Swap(&data[left], &data[right]);}Swap(&data[key_index], &data[left]);return left;//返回相遇点,key的当前下标
}
4. 递归核心代码
void QuickSort(int* data, int begin, int end)
{if (begin >= end)//当只有一个数据或是数组不存在时,不需要进行操作return;int key_index = begin;int left = begin;int right = end;while (left < right){//右边先走while (left < right && data[right] >= data[key_index])//右边找小{--right;}while (left < right && data[left] <= data[key_index])//左边找大{++left;}Swap(&data[left], &data[right]);}//此时left=rightSwap(&data[key_index], &data[left]);QuickSort(data, begin, left - 1);//左区间QuickSort(data, left+1,end);//右区间
}
5. 测试代码
#include<stdio.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}void QuickSort(int* data, int begin, int end)
{if (begin >= end)//当只有一个数据或是数组不存在时,不需要进行操作return;int key_index = begin;int left = begin;int right = end;while (left < right){//右边先走while (left < right && data[right] >= data[key_index])//右边找小{--right;}while (left < right && data[left] <= data[key_index])//左边找大{++left;}Swap(&data[left], &data[right]);}//此时left=rightSwap(&data[key_index], &data[left]);QuickSort(data, begin, left - 1);//左区间QuickSort(data, left+1,end);//右区间
}
int main()
{//int a[] = {6,1,2,7,9,3,4,5,10,8 };int a[] = {6,1,2,7,9,3,4,5,10,8 };print(a, sizeof(a) / sizeof(int));QuickSort(a, 0,sizeof(a) / sizeof(int)-1);print(a, sizeof(a) / sizeof(int));return 0;
}
6. 时间复杂度

(二)挖坑法


1. 单趟挖坑的代码
int PartSort(int* data, int left, int right)
{int key = data[left];int hole = left;//最左边坑所在的下标while (left < right){while (left<right && data[right]>=key)//右边找小{--right;}data[hole] = data[right];//填坑hole = right;//更新坑位while (left < right && data[left] <= key)//左边找大{++left;}data[hole] = data[left];hole = left;//更新坑位}data[hole] = key;return hole;//返回此时key的下标
}
2. 单趟测试代码
#include<stdio.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}int PartSort(int* data, int left, int right)
{int key = data[left];int hole = left;//最左边坑所在的下标while (left < right){while (left < right && data[right] >= key)//右边找小{--right;}data[hole] = data[right];//填坑hole = right;//更新坑位while (left < right && data[left] <= key)//左边找大{++left;}data[hole] = data[left];hole = left;//更新坑位}data[hole] = key;return hole;//返回此时key的下标
}
int main()
{//int a[] = {6,1,2,7,9,3,4,5,10,8 };int a[] = { 6,1,2,7,9,3,4,5,10,8 };print(a, sizeof(a) / sizeof(int));int x =PartSort(a, 0, sizeof(a) / sizeof(int) - 1);printf("%d\n", x);print(a, sizeof(a) / sizeof(int));return 0;
}
3. 递归挖坑代码
void QuickSort(int* data, int begin, int end)
{if (begin >= end)return;int left = begin;int right = end;int key = data[left];int hole = left;//最左边坑所在的下标while (left < right){while (left < right && data[right] >= key)//右边找小{--right;}data[hole] = data[right];//填坑hole = right;//更新坑位while (left < right && data[left] <= key)//左边找大{++left;}data[hole] = data[left];hole = left;//更新坑位}data[hole] = key;QuickSort(data, begin, hole - 1);//递归左边QuickSort(data, hole +1,end);//递归右边
}
4. 递归挖坑测试代码
#include<stdio.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}void QuickSort(int* data, int begin, int end)
{if (begin >= end)return;int left = begin;int right = end;int key = data[left];int hole = left;//最左边坑所在的下标while (left < right){while (left < right && data[right] >= key)//右边找小{--right;}data[hole] = data[right];//填坑hole = right;//更新坑位while (left < right && data[left] <= key)//左边找大{++left;}data[hole] = data[left];hole = left;//更新坑位}data[hole] = key;QuickSort(data, begin, hole - 1);//递归左边QuickSort(data, hole +1,end);//递归右边
}
int main()
{//int a[] = {6,1,2,7,9,3,4,5,10,8 };int a[] = { 6,1,2,7,9,3,4,5,10,8 };print(a, sizeof(a) / sizeof(int));QuickSort(a, 0, sizeof(a) / sizeof(int) - 1);print(a, sizeof(a) / sizeof(int));return 0;
}
(三)前后指针

- 最开始prev和cur相邻
- 当cur遇到比key大的值后,他们之间的值都是比key大的值
- 当cur找小,找到小的以后与++prev位置的值交换,相当于把大的值翻滚式向右边推,同时把小的换到左边
1. 单趟核心代码
int PartSort(int* data, int left, int right)
{int prev = left;int cur = left + 1;int key_index = left;while (cur <= right){if (data[cur] < data[key_index] && ++prev != cur)//如果prev和cur指向同一个数据没必要交换{Swap(&data[cur], &data[prev]);}++cur;}Swap(&data[key_index], &data[prev]);key_index = prev;return key_index;
}
2. 单趟测试代码
#include<stdio.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}int PartSort(int* data, int left, int right)
{int prev = left;int cur = left + 1;int key_index = left;while (cur <= right){if (data[cur] < data[key_index] && ++prev != cur)//如果prev和cur指向同一个数据没必要交换{Swap(&data[cur], &data[prev]);}++cur;}Swap(&data[key_index], &data[prev]);key_index = prev;return key_index;
}
int main()
{//int a[] = {6,1,2,7,9,3,4,5,10,8 };int a[] = { 6,1,2,7,9,3,4,5,10,8 };print(a, sizeof(a) / sizeof(int));int x = PartSort(a, 0, sizeof(a) / sizeof(int) - 1);printf("%d\n", x);print(a, sizeof(a) / sizeof(int));return 0;
}
3. 递归核心代码
void QuickSort(int* data, int begin, int end)
{if (begin >= end)return;//结束条件int prev = begin;int cur = begin + 1;int key_index = begin;while (cur <= end){if (data[cur] < data[key_index] && ++prev != cur)//如果prev和cur指向同一个数据没必要交换{Swap(&data[cur], &data[prev]);}++cur;}Swap(&data[key_index], &data[prev]);key_index = prev;//cur越界时,prev的位置QuickSort(data, begin, key_index-1);//递归排序左边QuickSort(data, key_index+1, end);//递归排序右边
}
4. 递归测试代码
#include<stdio.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}void QuickSort(int* data, int begin, int end)
{if (begin >= end)return;//结束条件int prev = begin;int cur = begin + 1;int key_index = begin;while (cur <= end){if (data[cur] < data[key_index] && ++prev != cur)//如果prev和cur指向同一个数据没必要交换{Swap(&data[cur], &data[prev]);}++cur;}Swap(&data[key_index], &data[prev]);key_index = prev;//cur越界时,prev的位置QuickSort(data, begin, key_index-1);//递归排序左边QuickSort(data, key_index+1, end);//递归排序右边
}
int main()
{//int a[] = {6,1,2,7,9,3,4,5,10,8 };int a[] = { 6,1,2,7,9,3,4,5,10,8 };print(a, sizeof(a) / sizeof(int));QuickSort(a, 0, sizeof(a) / sizeof(int) - 1);print(a, sizeof(a) / sizeof(int));return 0;
}
(四)非递归实现(栈)


#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
void print(int* data, int n)
{for (int i = 0; i < n; i++){cout << data[i]<<" ";}cout << endl;
}
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
int PartSort(int* data, int begin, int end)
{int key_index = begin;int left = begin;int right = end;while (left < right){//右边先走while (left < right && data[right] >= data[key_index])//右边找小{--right;}while (left < right && data[left] <= data[key_index])//左边找大{++left;}Swap(&data[left], &data[right]);}Swap(&data[key_index], &data[left]);return left;//返回相遇点,key的当前下标
}void QuickSort(int* data, int begin, int end)
{stack<int>s;s.push(begin);s.push(end);while (!s.empty()){int right = s.top();s.pop();int left = s.top();s.pop();int key_index = PartSort(data, left, right);//一趟快排以后key新的下标//[left,key_index-1] key_index [key_index+1,right]if (key_index+1 < right)//右区间合理则先入栈{s.push(key_index + 1);s.push(right);}if (left < key_index - 1)//左区间入栈{s.push(left);s.push(key_index - 1);}}
}
int main()
{//int a[] = {6,1,2,7,9,3,4,5,10,8 };int a[] = { 6,1,2,7,9,3,4,5,10,8 };print(a, sizeof(a) / sizeof(int));QuickSort(a, 0, sizeof(a) / sizeof(int) - 1);print(a, sizeof(a) / sizeof(int));return 0;
}
六、归并排序

1. 递归核心代码
void _MergeSort(int* data, int left, int right, int* tmp)
{if (left == right)//当只有一个数据的时候不再分解return;//结束条件int mid = (left+right)/2;//[left,mid] [mid+1,right]_MergeSort(data, left, mid, tmp);_MergeSort(data, mid + 1, right, tmp);int begin1 = left, end1 = mid;int begin2 = mid + 1, end2 = right;int k = left;//每一个回合都从下标为left位置处在tmp中存放数据while (begin1 <= end1 && begin2 <= end2){if (data[begin1] <= data[begin2]){tmp[k++] = data[begin1++];}else{tmp[k++] = data[begin2++];}}while (begin1 <= end1){tmp[k++] = data[begin1++];}while (begin2 <= end2){tmp[k++] = data[begin2++];}memcpy(data + left, tmp + left, sizeof(int) * (right - left+1));
}
2. 测试代码

#include<stdio.h>
#include<malloc.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ",data[i]);}printf("\n");
}void _MergeSort(int* data, int left, int right, int* tmp)
{if (left == right)//当只有一个数据的时候不再分解return;//结束条件int mid = (left+right)/2;//[left,mid] [mid+1,right]_MergeSort(data, left, mid, tmp);_MergeSort(data, mid + 1, right, tmp);int begin1 = left, end1 = mid;int begin2 = mid + 1, end2 = right;int k = left;//每一个回合都从下标为left位置处在tmp中存放数据while (begin1 <= end1 && begin2 <= end2){if (data[begin1] <= data[begin2]){tmp[k++] = data[begin1++];}else{tmp[k++] = data[begin2++];}}while (begin1 <= end1){tmp[k++] = data[begin1++];}while (begin2 <= end2){tmp[k++] = data[begin2++];}memcpy(data + left, tmp + left, sizeof(int) * (right - left+1));
}void MergeSort(int* data, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");exit(-1);}_MergeSort(data, 0, n - 1, tmp);free(tmp);tmp = NULL;
}int main()
{int a[] = {10,6,7,1,3,9,4,2};print(a, sizeof(a) / sizeof(int));MergeSort(a, sizeof(a) / sizeof(int) );print(a, sizeof(a) / sizeof(int));return 0;
}
3. 非递归核心代码

void _MergeSort(int* data, int* tmp,int begin1,int end1,int begin2,int end2)
{int j = begin1;int k = begin1;while (begin1 <= end1 && begin2 <= end2){if (data[begin1]<=data[begin2]){tmp[k++] = data[begin1++];}else{tmp[k++] = data[begin2++];}}while (begin1 <= end1){tmp[k++] = data[begin1++];}while (begin2 <= end2){tmp[k++] = data[begin2++];}for (j; j <= end2; j++)//一个一个拷贝{data[j] = tmp[j];}//等价形式//memcpy(data+j, tmp+j, sizeof(int) * (end2 - j)+1);//左闭右闭}void MergeSort(int* data, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");exit(-1);}int gap = 1;while (gap < n){for (int i = 0; i < n; i += 2*gap)//i+2gap是下一组begin1的起始下标{int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = begin2 + gap - 1;if (end1 >= n || begin2 >= n)//最后一组数据的第一个区间的后半部分不存在或者第二个区间整个不存在,都不需要进行合并{break;//意味着不需要进行_MergeSort,不用进行合并操作}if (end2 >= n){end2 = n - 1;//最后一组数据的第2个区间的后半部分超出了}_MergeSort(data, tmp, begin1, end1, begin2, end2);}gap = gap * 2;}free(tmp);tmp = NULL;
}
4. 测试代码
#include<stdio.h>
#include<malloc.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ",data[i]);}printf("\n");
}void _MergeSort(int* data, int* tmp,int begin1,int end1,int begin2,int end2)
{int j = begin1;int k = begin1;while (begin1 <= end1 && begin2 <= end2){if (data[begin1]<=data[begin2]){tmp[k++] = data[begin1++];}else{tmp[k++] = data[begin2++];}}while (begin1 <= end1){tmp[k++] = data[begin1++];}while (begin2 <= end2){tmp[k++] = data[begin2++];}for (j; j <= end2; j++)//一个一个拷贝{data[j] = tmp[j];}//等价形式//memcpy(data+j, tmp+j, sizeof(int) * (end2 - j)+1);//左闭右闭}void MergeSort(int* data, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");exit(-1);}int gap = 1;while (gap < n){for (int i = 0; i < n; i += 2*gap)//i+2gap是下一组begin1的起始下标{int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = begin2 + gap - 1;if (end1 >= n || begin2 >= n)//最后一组数据的第一个区间的后半部分不存在或者第二个区间整个不存在,都不需要进行合并{break;//意味着不需要进行_MergeSort,不用进行合并操作}if (end2 >= n){end2 = n - 1;//最后一组数据的第2个区间的后半部分超出了}_MergeSort(data, tmp, begin1, end1, begin2, end2);}gap = gap * 2;}free(tmp);tmp = NULL;
}int main()
{int a[] = {10,6,7,1,3,9,4,2,5};print(a, sizeof(a) / sizeof(int));MergeSort(a, sizeof(a) / sizeof(int) );print(a, sizeof(a) / sizeof(int));return 0;
}
七、堆排序
1. 向下调整
void AdjustDown(int* data,int n, int parent)//向下调整
{int child = 2 * parent + 1;//先假设左孩子结点的值最小while (child < n){if (child+1<n && data[child+1] < data[child]){++child;}if (data[child] < data[parent])//排升序{Swap(&data[child], &data[parent]);parent = child;child = 2 * parent + 1;}else//已成堆break;}}
2. 建堆
void CreateHeap(int* data, int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(data, n, i);}
}
#include<stdio.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}void AdjustDown(int* data, int n, int parent)//向下调整
{int child = 2 * parent + 1;//先假设左孩子结点的值最小while (child < n){if (child + 1 < n && data[child + 1] < data[child]){++child;}if (data[child] < data[parent])//排升序{Swap(&data[child], &data[parent]);parent = child;child = 2 * parent + 1;}else//已成堆break;}}void CreateHeap(int* data, int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(data, n, i);}
}
int main()
{int a[] = { 2,7,4,6,3,8,1 };print(a, sizeof(a) / sizeof(int));CreateHeap(a, sizeof(a) / sizeof(int));print(a, sizeof(a) / sizeof(int));return 0;
}
3. 堆排序代码
void HeapSort(int* data, int n)
{//建堆for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(data, n, i);//建小根堆}//排降序for (int i = 0; i < n; i++){Swap(&data[0], &data[n - 1 - i]);//将堆顶元素和最后一个元素互换,再迭代向下调整AdjustDown(data, n - 1- i, 0);//n-1-i是重新建堆的数据个数}
}
#include<stdio.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}void AdjustDown(int* data, int n, int parent)//向下调整
{int child = 2 * parent + 1;//先假设左孩子结点的值最小while (child < n){if (child + 1 < n && data[child + 1] < data[child]){++child;}if (data[child] < data[parent])//排升序{Swap(&data[child], &data[parent]);parent = child;child = 2 * parent + 1;}else//已成堆break;}}void HeapSort(int* data, int n)
{//建堆for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(data, n, i);//建小根堆}//调整for (int i = 0; i < n; i++){Swap(&data[0], &data[n - 1 - i]);//将堆顶元素和最后一个元素互换,再迭代向下调整AdjustDown(data, n - 1- i, 0);//n-1-i是重新建堆的数据个数}
}
int main()
{int a[] = { 2,7,4,6,3,8,1 };print(a, sizeof(a) / sizeof(int));HeapSort(a, sizeof(a) / sizeof(int));print(a, sizeof(a) / sizeof(int));return 0;
}
4. 向上调整
void AdjustUp(int* data, int n, int child)//向上调整
{int parent = (child - 1) / 2;while (child > 0){if (data[child] < data[parent]){Swap(&data[child], &data[parent]);child = parent;parent = (child - 1) / 2;}elsebreak;}
}
5. 测试
#include<stdio.h>
void print(int* data, int n)
{for (int i = 0; i < n; i++){printf("%d ", data[i]);}printf("\n");
}
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}void AdjustUp(int* data, int n, int child)//向上调整
{int parent = (child - 1) / 2;while (child > 0){if (data[child] < data[parent]){Swap(&data[child], &data[parent]);child = parent;parent = (child - 1) / 2;}elsebreak;}
}void CreateHeap(int* data, int n)
{//建堆for (int i = n - 1; i >= 0; --i){AdjustUp(data, n, i);//建小根堆}
}
int main()
{int a[] = { 2,7,4,6,3,8,1 };print(a, sizeof(a) / sizeof(int));CreateHeap(a, sizeof(a) / sizeof(int));print(a, sizeof(a) / sizeof(int));return 0;
}
相关文章:
七大排序完整版
目录 一、直接插入排序 (一)单趟直接插入排 1.分析核心代码 2.完整代码 (二)全部直接插入排 1.分析核心代码 2.完整代码 (三)时间复杂度和空间复杂度 二、希尔排序 (一)对…...
C语言的数据类型简介
一、基本类型 (1)六种基本类型 **字符串常量和字符常量的不同 1)‘a’为字符常量,”a”为字符串常量 2)每个字符串的结尾,编译器会自动添加一个结束标志位‘\0’ “a”包含两个字符’a’和’\0’ &#x…...
Fei-Fei Li-Lecture 16:3D Vision 【斯坦福大学李飞飞CV课程第16讲:3D Vision】
目录 P1 2D Detection and Segmentation P2 Video 2D time series P3 Focus on Two Problems P4 Many more topics in 3D Vision P5-10 Multi-View CNN P11 Experiments – Classification & Retrieval P12 3D Shape Representations P13--17 3D Shape Represen…...
【计算机视觉】YOLO 入门:训练 COCO128 数据集
一、COCO128 数据集 我们以最近大热的YOLOv8为例,回顾一下之前的安装过程: %pip install ultralytics import ultralytics ultralytics.checks()这里选择训练的数据集为:COCO128 COCO128是一个小型教程数据集,由COCOtrain2017中…...
【数分面试答疑】XX场景如何分析问题的思考
问题: 如何分析消费贷客户的用款活跃度,简单列出分析报告的思路框架 解答 这个问题是一个典型的数据分析类的面试问题,主要考察面试者对于消费贷客户的用款活跃度分析的理解和方法,以及对于数据分析报告的撰写和呈现的能力。回…...
html中如何用vue语法,并使用UI组件库 ,html中引入vue+ant-design-vue或者vue+element-plus
html中如何用vue语法,并使用UI组件库 前言 先说一下本次应用的场景,本次项目中,需要引入github中别人写好的插件,插件比较大,没有方法直接在自己项目中,把别人的项目打包合并生成html(类似于前…...
【数据结构】二叉数的存储与基本操作的实现
文章目录 🍀二叉树的存储🌳二叉树的基本操作🐱👤二叉树的创建🐱👓二叉树的遍历🎡前中后序遍历📌前序遍历📌中序遍历📌后续遍历 🛫层序遍历&am…...
使用 Netty 实现群聊功能的步骤和注意事项
文章目录 前言声明功能说明实现步骤WebSocket 服务启动Channel 初始化HTTP 请求处理HTTP 页面内容WebSocket 请求处理 效果展示总结 前言 通过之前的文章介绍,我们可以深刻认识到Netty在网络编程领域的卓越表现和强大实力。这篇文章将介绍如何利用 Netty 框架开发一…...
一篇文章搞定《WebView的优化及封装》
一篇文章搞定《WebView的优化及封装》 前言WebView的过程分析确定优化方案一、预加载,复用缓冲池(初始化优化)优化的解析说明具体的实现 二、预置模版(请求、渲染优化)优化的解析说明具体的实现1、离线包2、预获取数据…...
FreeSWITCH 1.10.10 简单图形化界面5 - 使用百度TTS
FreeSWITCH 1.10.10 简单图形化界面5 - 使用百度TTS 0、 界面预览1、注册百度AI开放平台,开通语音识别服务2、获取AppID/API Key/Secret Key3、 安装百度语音合成sdk4、合成代码5、在PBX中使用百度TTS6、音乐文件-TTS7、拨号规则-tts_command 0、 界面预览 http://…...
DP读书:不知道干什么就和我一起读书吧
DP读书:不知道干什么就和我一起读书吧 为啥写博客:好处一:记录自己的学习过程优点二:让自己在各大社群里不那么尴尬推荐三:坚持下去,找到一个能支持自己的伙伴 虽然清楚知识需要靠时间沉淀,但在…...
【Linux】进程通信 — 信号(上篇)
文章目录 📖 前言1. 什么是信号1.1 认识信号:1.2 信号的产生:1.3 信号的异步:1.4 信号的处理: 2. 前后台进程3. 系统接口3.1 signal:3.1 - 1 不能被捕捉的信号 3.2 kill:3.2 - 1 killall 3.3 ra…...
JS弃之可惜食之无味的代码冷知识
JS代码冷知识大全 1. 变量提升与暂死 在JavaScript中,变量提升是一个有趣且容易让人误解的概念。在代码中,变量和函数声明会在其所在作用域的顶部被提升,但是初始化并不会被提升。这可能导致在声明之前就使用变量,结果为undefin…...
数据结构初阶--排序
目录 一.排序的基本概念 1.1.什么是排序 1.2.排序算法的评价指标 1.3.排序的分类 二.插入排序 2.1.直接插入排序 2.2.希尔排序 三.选择排序 3.1.直接选择排序 3.2.堆排序 重建堆 建堆 排序 四.交换排序 4.1.冒泡排序 4.2.快速排序 快速排序的递归实现 法一&a…...
赴日IT 如何提高去日本做程序员的几率?
其实想去日本做IT工作只要满足学历、日语、技术三个必要条件,具备这些条件应聘就好,不具备条件你就想办法具备这些条件,在不具备条件之前不要轻易到日本去,日本IT行业虽然要求技术没有国内那么高,但也不是随便好进入的…...
c# 使用了 await、asnync task.run 三者结合使用
在 C# 异步编程中,await 和 async 关键字结合使用可以让你更方便地编写异步代码,而无需直接使用 Task.Run。然而,有时候你可能仍然需要使用 Task.Run 来在后台线程上执行某些工作,这取决于你的代码逻辑和需求。 await 和 async 关…...
C#获取屏幕缩放比例
现在1920x1080以上分辨率的高分屏电脑渐渐普及了。我们会在Windows的显示设置里看到缩放比例的设置。在Windows桌面客户端的开发中,有时会想要精确计算窗口的面积或位置。然而在默认情况下,无论WinForms的Screen.Bounds.Width属性还是WPF中SystemParamet…...
Rn实现省市区三级联动
省市区三级联动选择是个很频繁的需求,但是查看了市面上很多插件不是太老不维护就是不满足需求,就试着实现一个 这个功能无任何依赖插件 功能略简单,但能实现需求 核心代码也尽力控制在了60行左右 pca-code.json树型数据来源 Administrative-d…...
SpringCloud学习笔记(十)_SpringCloud监控
今天我们来学习一下actuator这个组件,它不是SpringCloud之后才有的,而是SpringBoot的一个starter,Spring Boot Actuator。我们使用SpringCloud的时候需要使用这个组件对应用程序进行监控与管理 在SpringBoot2.0版本中,actuator可以…...
测试理论与方法----测试流程的第二个环节:测试计划
二、软件测试分类与测试计划 1、软件测试的分类(理解掌握) 根绝需求规格说明书,在设计阶段会产出的两个文档: 概要设计(HLD):设计软件的结构,包含软件的组成,模块之间的层次关系,模块与模块之间的调用关系…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
