当前位置: 首页 > 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;模块与模块之间的调用关系…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...