当前位置: 首页 > news >正文

七大排序完整版

目录

一、直接插入排序

(一)单趟直接插入排

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;
}

相关文章:

七大排序完整版

目录 一、直接插入排序 &#xff08;一&#xff09;单趟直接插入排 1.分析核心代码 2.完整代码 &#xff08;二&#xff09;全部直接插入排 1.分析核心代码 2.完整代码 &#xff08;三&#xff09;时间复杂度和空间复杂度 二、希尔排序 &#xff08;一&#xff09;对…...

C语言的数据类型简介

一、基本类型 &#xff08;1&#xff09;六种基本类型 **字符串常量和字符常量的不同 1&#xff09;‘a’为字符常量&#xff0c;”a”为字符串常量 2&#xff09;每个字符串的结尾&#xff0c;编译器会自动添加一个结束标志位‘\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为例&#xff0c;回顾一下之前的安装过程&#xff1a; %pip install ultralytics import ultralytics ultralytics.checks()这里选择训练的数据集为&#xff1a;COCO128 COCO128是一个小型教程数据集&#xff0c;由COCOtrain2017中…...

【数分面试答疑】XX场景如何分析问题的思考

问题&#xff1a; 如何分析消费贷客户的用款活跃度&#xff0c;简单列出分析报告的思路框架 解答 这个问题是一个典型的数据分析类的面试问题&#xff0c;主要考察面试者对于消费贷客户的用款活跃度分析的理解和方法&#xff0c;以及对于数据分析报告的撰写和呈现的能力。回…...

html中如何用vue语法,并使用UI组件库 ,html中引入vue+ant-design-vue或者vue+element-plus

html中如何用vue语法&#xff0c;并使用UI组件库 前言 先说一下本次应用的场景&#xff0c;本次项目中&#xff0c;需要引入github中别人写好的插件&#xff0c;插件比较大&#xff0c;没有方法直接在自己项目中&#xff0c;把别人的项目打包合并生成html&#xff08;类似于前…...

【数据结构】二叉数的存储与基本操作的实现

文章目录 &#x1f340;二叉树的存储&#x1f333;二叉树的基本操作&#x1f431;‍&#x1f464;二叉树的创建&#x1f431;‍&#x1f453;二叉树的遍历&#x1f3a1;前中后序遍历&#x1f4cc;前序遍历&#x1f4cc;中序遍历&#x1f4cc;后续遍历 &#x1f6eb;层序遍历&am…...

使用 Netty 实现群聊功能的步骤和注意事项

文章目录 前言声明功能说明实现步骤WebSocket 服务启动Channel 初始化HTTP 请求处理HTTP 页面内容WebSocket 请求处理 效果展示总结 前言 通过之前的文章介绍&#xff0c;我们可以深刻认识到Netty在网络编程领域的卓越表现和强大实力。这篇文章将介绍如何利用 Netty 框架开发一…...

一篇文章搞定《WebView的优化及封装》

一篇文章搞定《WebView的优化及封装》 前言WebView的过程分析确定优化方案一、预加载&#xff0c;复用缓冲池&#xff08;初始化优化&#xff09;优化的解析说明具体的实现 二、预置模版&#xff08;请求、渲染优化&#xff09;优化的解析说明具体的实现1、离线包2、预获取数据…...

FreeSWITCH 1.10.10 简单图形化界面5 - 使用百度TTS

FreeSWITCH 1.10.10 简单图形化界面5 - 使用百度TTS 0、 界面预览1、注册百度AI开放平台&#xff0c;开通语音识别服务2、获取AppID/API Key/Secret Key3、 安装百度语音合成sdk4、合成代码5、在PBX中使用百度TTS6、音乐文件-TTS7、拨号规则-tts_command 0、 界面预览 http://…...

DP读书:不知道干什么就和我一起读书吧

DP读书&#xff1a;不知道干什么就和我一起读书吧 为啥写博客&#xff1a;好处一&#xff1a;记录自己的学习过程优点二&#xff1a;让自己在各大社群里不那么尴尬推荐三&#xff1a;坚持下去&#xff0c;找到一个能支持自己的伙伴 虽然清楚知识需要靠时间沉淀&#xff0c;但在…...

【Linux】进程通信 — 信号(上篇)

文章目录 &#x1f4d6; 前言1. 什么是信号1.1 认识信号&#xff1a;1.2 信号的产生&#xff1a;1.3 信号的异步&#xff1a;1.4 信号的处理&#xff1a; 2. 前后台进程3. 系统接口3.1 signal&#xff1a;3.1 - 1 不能被捕捉的信号 3.2 kill&#xff1a;3.2 - 1 killall 3.3 ra…...

JS弃之可惜食之无味的代码冷知识

JS代码冷知识大全 1. 变量提升与暂死 在JavaScript中&#xff0c;变量提升是一个有趣且容易让人误解的概念。在代码中&#xff0c;变量和函数声明会在其所在作用域的顶部被提升&#xff0c;但是初始化并不会被提升。这可能导致在声明之前就使用变量&#xff0c;结果为undefin…...

数据结构初阶--排序

目录 一.排序的基本概念 1.1.什么是排序 1.2.排序算法的评价指标 1.3.排序的分类 二.插入排序 2.1.直接插入排序 2.2.希尔排序 三.选择排序 3.1.直接选择排序 3.2.堆排序 重建堆 建堆 排序 四.交换排序 4.1.冒泡排序 4.2.快速排序 快速排序的递归实现 法一&a…...

赴日IT 如何提高去日本做程序员的几率?

其实想去日本做IT工作只要满足学历、日语、技术三个必要条件&#xff0c;具备这些条件应聘就好&#xff0c;不具备条件你就想办法具备这些条件&#xff0c;在不具备条件之前不要轻易到日本去&#xff0c;日本IT行业虽然要求技术没有国内那么高&#xff0c;但也不是随便好进入的…...

c# 使用了 await、asnync task.run 三者结合使用

在 C# 异步编程中&#xff0c;await 和 async 关键字结合使用可以让你更方便地编写异步代码&#xff0c;而无需直接使用 Task.Run。然而&#xff0c;有时候你可能仍然需要使用 Task.Run 来在后台线程上执行某些工作&#xff0c;这取决于你的代码逻辑和需求。 await 和 async 关…...

C#获取屏幕缩放比例

现在1920x1080以上分辨率的高分屏电脑渐渐普及了。我们会在Windows的显示设置里看到缩放比例的设置。在Windows桌面客户端的开发中&#xff0c;有时会想要精确计算窗口的面积或位置。然而在默认情况下&#xff0c;无论WinForms的Screen.Bounds.Width属性还是WPF中SystemParamet…...

Rn实现省市区三级联动

省市区三级联动选择是个很频繁的需求&#xff0c;但是查看了市面上很多插件不是太老不维护就是不满足需求&#xff0c;就试着实现一个 这个功能无任何依赖插件 功能略简单&#xff0c;但能实现需求 核心代码也尽力控制在了60行左右 pca-code.json树型数据来源 Administrative-d…...

SpringCloud学习笔记(十)_SpringCloud监控

今天我们来学习一下actuator这个组件&#xff0c;它不是SpringCloud之后才有的&#xff0c;而是SpringBoot的一个starter&#xff0c;Spring Boot Actuator。我们使用SpringCloud的时候需要使用这个组件对应用程序进行监控与管理 在SpringBoot2.0版本中&#xff0c;actuator可以…...

测试理论与方法----测试流程的第二个环节:测试计划

二、软件测试分类与测试计划 1、软件测试的分类(理解掌握) 根绝需求规格说明书&#xff0c;在设计阶段会产出的两个文档&#xff1a; 概要设计(HLD)&#xff1a;设计软件的结构&#xff0c;包含软件的组成&#xff0c;模块之间的层次关系&#xff0c;模块与模块之间的调用关系…...

3大场景×5项优化:ComfyUI视频合成VHS_VideoCombine节点全场景应用指南

3大场景5项优化&#xff1a;ComfyUI视频合成VHS_VideoCombine节点全场景应用指南 【免费下载链接】ComfyUI-VideoHelperSuite Nodes related to video workflows 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-VideoHelperSuite 一、基础认知&#xff1a;视频合…...

AMD Ryzen SDT调试工具:突破性实战指南,让你的处理器性能飙升200%

AMD Ryzen SDT调试工具&#xff1a;突破性实战指南&#xff0c;让你的处理器性能飙升200% 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. …...

Unity Shader UV 坐标与纹理平铺Tiling Offset 深度解析

从 UV 空间的数学本质出发&#xff0c;理解 URP 中纹理坐标的缩放&#xff08;Tiling&#xff09;与偏移&#xff08;Offset&#xff09;控制原理&#xff0c; 并掌握 Shader Graph、HLSL、C# 三种维度的实践技巧。UV 坐标系基础在实时渲染中&#xff0c;UV 坐标是将二维纹理贴…...

别再只用ZF和MMSE了!手把手教你用MATLAB实现ML信号检测(附完整代码与性能对比)

突破传统线性检测&#xff1a;MATLAB实战ML信号检测全解析 在无线通信系统的接收端设计领域&#xff0c;信号检测算法的选择直接影响着系统性能与实现复杂度之间的平衡。许多初学者往往止步于迫零(ZF)和最小均方误差(MMSE)这两种线性检测方法&#xff0c;却忽视了最大似然(ML)检…...

全面只使用sessionid来验证登录-----客户端只保留sessionid

虽然说sessionid 也是可以伪造的&#xff0c;可以快速发送伪造的sessionid,但是因为sessionid是32位的随机字符串&#xff0c;暴力破解需要几亿年&#xff0c;安全性比user_id1,user_id2 高得多。不过一个有意思的事情是&#xff1a;如果我把user_id1改成 user_id32位随机字符串…...

ZYNQ PS侧DDR3内存配置避坑指南:以ACZ702开发板为例,手把手教你搞定MT41K128M16

ZYNQ PS侧DDR3内存配置实战&#xff1a;从硬件原理到Vivado参数设置全解析 当你第一次拿到ACZ702这样的ZYNQ开发板&#xff0c;准备配置PS侧的DDR3内存时&#xff0c;是否遇到过这样的困惑&#xff1a;为什么在Vivado中找不到DDR管脚约束选项&#xff1f;为什么按照传统FPGA的D…...

智能车调参手记:我用Kp=200, Ki=60, Kd=40让小车稳如老狗

智能车调参手记&#xff1a;我用Kp200, Ki60, Kd40让小车稳如老狗 凌晨三点的实验室里&#xff0c;咖啡杯已经见底&#xff0c;眼前的智能车在测试跑道上又一次冲出了弯道。这已经是本周第七次熬夜调试&#xff0c;上坡时的速度波动问题始终困扰着我们。就在准备放弃的时候&…...

离谱了,简历写了这个项目薪资直接涨了 80%!!

报喜了&#xff01;&#xff01;&#xff01;前阵子帮一个粉丝修改简历&#xff0c;只是在项目经历里加了一个“不起眼”的项目&#xff0c;优化了表述逻辑&#xff0c;没想到他面试3家公司&#xff0c;2家给了offer&#xff0c;薪资直接比上一份涨了80%&#xff01;其实很多人…...

突发!国行苹果 AI 凌晨偷跑又紧急下线

3 月 31 日凌晨&#xff0c;大量升级 iOS 26.4 的国行 iPhone 16 及后续机型用户&#xff0c;突然发现设置里 “Siri” 变成 “Apple 智能与 Siri”&#xff0c;可下载 9.5GB 本地 AI 模型&#xff0c;解锁实时翻译、视觉智能、照片消除等全套功能。不过这场“惊喜”仅持续了数…...

3GPP TS 23.256标准解读:无人机广播远程识别码(Broadcast Remote ID)到底是怎么工作的?

3GPP TS 23.256标准深度解析&#xff1a;无人机广播远程识别码的技术实现与合规路径 当一架无人机在城市上空盘旋时&#xff0c;地面人员如何快速确认它的合法身份&#xff1f;监管机构又该如何在密集的无线电环境中精准捕捉每一架飞行器的信息&#xff1f;这些问题的答案&…...