//1.冒泡排序:
#pragma once
#include<stdio.h>
void Swap5(int* a, int* b)
{
int c = *a;
*a = *b;
*b = c;
}
void Print5(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
//冒泡排序
//思想:
//9 5 2 7 4 1 3
//1.两个数之间相互比较大小,每次将较大的值的数字放在后面
//2.循环整个数组,一次遍历后就将最大值放在了最后
//3.在--size,在次循环
void Sort5(int arr[], int size)
{
while (size)
{
for (int i = 1; i < size; i++)
{
if (arr[i - 1] > arr[i])
{
Swap5(&arr[i - 1], &arr[i]);
}
}
size--;
}
}
void Text5()
{
int arr[] = { 9,5,2,7,4,1,3 };
int size = sizeof(arr) / sizeof(arr[0]);
Print5(arr, size);
Sort5(arr, size);
Print5(arr, size);
}
//////////////////////////////////////////////////////////////////////////////////
//2.堆排序
#pragma once
#include<stdio.h>
void Swap(int* a, int* b)
{
int i = *a;
*a = *b;
*b = i;
}
//向下调整(找最大)
void Heapify(int arr[], int size, int index)
{
while (1)
{
int leftindex = (2 * index) + 1;
int rightindex = (2 * index) + 2;
//如果左孩子不存在,则右孩子也一定不存在
if (leftindex >= size)
{
return;
}
//判断是否有右孩子并找到最大孩子
int maxindex = leftindex;
if (rightindex < size && arr[rightindex] > arr[leftindex])
{
maxindex = rightindex;
}
//比较最大孩子与根的大小
if (arr[maxindex] >= arr[index])
{
Swap(&arr[maxindex], &arr[index]);
}
index = maxindex;
}
}
//3.创建堆
void CreatHeapify(int arr[], int size)
{
//将数组逻辑上的储存看作二叉树
//从最后一个非叶子节点开始一次从下到上一次调整二叉树,使二叉树满足堆的特点
for (int i = (size - 2) / 2; i >= 0; i--)
{
//这里的传参有点问题?
Heapify(arr, size, i);
}
}
//二叉树的堆排序(升序)
void Sort(int arr[], int size)
{
//将数组创建成为堆
CreatHeapify(arr, size);
//每次取出堆顶元素(最大值)与最后一个元素互换,size--
//在一次从新数组的堆顶开始一次下调,建成新堆
//循环,直到size = 0
while (size > 0)
{
Swap(&arr[0], &arr[size - 1]);
size--;
Heapify(arr, size, 0);
}
}
void Print(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void Text1()
{
int arr[] = { 9,3,1,2,6,5,7,4,9,0,3 };
int size = sizeof(arr) / sizeof(arr[0]);
Print(arr, size);
Sort(arr, size);
Print(arr, size);
}
//////////////////////////////////////////////////////////////////////////////////
//3.插入排序
#pragma once
#include<stdio.h>
void Print3(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void Swap3(int* a, int* b)
{
int i = *a;
*a = *b;
*b = i;
}
//9, 5, 2, 7, 4, 1
//5, 9, 2, 7, 4, 1
void Insert(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
for (int j = i; j > 0 ; j--)
{
if (arr[j] < arr[j - 1])
{
Swap(&arr[j], &arr[j - 1]);
}
else
{
break;
}
}
}
}
void Text3()
{
int arr[] = { 9, 5, 2, 7, 4, 1 };
int size = sizeof(arr) / sizeof(arr[0]);
Print3(arr, size);
Insert(arr, size);
Print3(arr, size);
}
//////////////////////////////////////////////////////////////////////////////
//4.归并排序
#pragma once
#include<stdio.h>
#include<stdlib.h>
void Swap7(int* a, int* b)
{
int c = *a;
*a = *b;
*b = c;
}
void Print7(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
//归并排序
//思想:
//1.将数组分成已经有序的两个数组,在合并这两个数组
//2.如果整个数组都是无序的,就在将两个数组分别分为两个数组,
//3.直到所分的数组中只有一个元素的时候,那么它肯定是有序的
//4.然后在一次合并这些分开的数组
void Merge(int array[], int low, int mid, int high, int extra[]) {
// [low, high)
int i = low; // [low, mid)
int j = mid; // [mid, high)
int k = low; // extra[low, high)
while (i < mid && j < high) {
if (array[i] <= array[j]) { // = 保证了稳定性
extra[k++] = array[i++];
}
else {
extra[k++] = array[j++];
}
}
while (i < mid) {
extra[k++] = array[i++];
}
while (j < high) {
extra[k++] = array[j++];
}
for (int x = low; x < high; x++) {
array[x] = extra[x];
}
}
// [low, high)
void MergeSortInner(int array[], int low, int high, int extra[]) {
// 2. 直到 size == 1 || size == 0
if (low >= high) {
// size == 0
return;
}
if (low + 1 == high) { // [3, 4)
// size == 1
return;
}
// 1. 平均切割
int mid = low + (high - low) / 2;
// 2. 分治处理左右两个小区间
MergeSortInner(array, low, mid, extra); // [low, mid)
MergeSortInner(array, mid, high, extra); // [mid, high)
// 3. 合并两个有序数组
Merge(array, low, mid, high, extra);
}
void Sort7(int array[], int size) {
int *extra = (int *)malloc(sizeof(int)* size);
MergeSortInner(array, 0, size, extra);
free(extra);
}
void Text7()
{
int arr[] = { 9,5,2,7,4,1,3 };
int size = sizeof(arr) / sizeof(arr[0]);
Print7(arr, size);
Sort7(arr, size);
Print7(arr, size);
}
////////////////////////////////////////////////////////////////////////////////
//5.快排
#pragma once
#include<stdio.h>
void Swap4(int* a, int* b)
{
int c = *a;
*a = *b;
*b = c;
}
void Print4(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
//挖坑
//思想:
//1.为数组找一个基准值并保存下来(我们取最右边的数字)
//2.begin找大于基准值的数并赋值给end下标所在的数
//3.end找小于基准值的数并赋值给begin下标所在的数
//4.当begin 与 end 的值相等的时候,退出循环
//5.将保存的基准值赋值给 begin 下标所在数字,并返回下标的值,就为分割的下标
int Partition_1(int arr[], int left, int right)
{
//找基准值(以最右边的right作为基准值)
int begin = left;
int end = right;
int temp = arr[right];
while (begin < end)
{
while (begin < end && arr[begin] <= temp)
{
begin++;
}
//这里找到比基准值大的数
arr[end] = arr[begin];
while (begin < end && arr[end] >= temp)
{
end--;
}
//这里找到比基准值小的数
arr[begin] = arr[end];
}
arr[begin] = temp;
return begin;
}
//Hover
//思想:
//1.与挖坑相同,需要先定义一个基准值(我们取最右边的数字)
//2.由 begin 开始寻找大于基准值的数
//3.end 寻找小于基准值的数字
//4.将 begin 与 end 交换,确保大于基准值的数字在右边,小于基准值的在左边
//5.当 begin 与 end 相等的时候退出循环并 将基准值与 begin 下标所在数字与基准值交换
//6.返回下标,就是分割的下标
int Partition_2(int arr[], int left, int right)
{
int begin = left;
int end = right;
int temp = arr[right];
while (begin < end)
{
while (begin < end && arr[begin] <= temp)
{
begin++;
}
//这里保证了出来的arr[begin]值一定大于基准值temp
while (begin < end && arr[end] >= temp)
{
end--;
}
//这里保证了出来的arr[end]值一定小于基准值temp
//交换这两个值,保证大于基准值的在右边,小于基准值的在左边
Swap4(&arr[begin], &arr[end]);
}
//当 begin 与 end 的值相等的时候退出循环,
//及保证了分治的条件,在将基准值与 begin 下标的数字交换位置
Swap(&arr[begin], &arr[right]);
//这里的基准值必须取rihgt下标所在数,不能用保存的变量temp,否则就会改变数组中的元素
return begin;
}
//前后下标
//思想:
//9 5 2 7 4 1
//1.同样的,需要先定义一个基准值(我们取最右边的数字)
//2.由 i 开始寻找小于基准值的数,index 作为标记,在 index 的左边都是小于基准值的
//3.找到后将 i 与 index 交换,后 ++index ,确保小于基准值的数字在左边,大于于基准值的在右边
//5.将数组内的数字都寻找完的时候退出循环并 将基准值与 index 下标所在数字交换
//6.返回下标,就是分割的下标
int Partition_3(int arr[], int left, int right)
{
int index = left;
for (int i = left; i < right; i++)
{
if (arr[i] < arr[right])
{
Swap(&arr[i], &arr[index]);
index++;
}
}
Swap(&arr[index], &arr[right]);
return index;
}
void Sort4(int arr[], int left, int right)
{
if (left == right)
{
return;
}
if (left > right)
{
return;
}
int index = Partition_2(arr, left, right);
//这里自己写的时候出错了,原因:
//分治的时候没有找准边界,边界应该是 左闭右开 的范围
//(可以这样理解,当我们分割的时候,下标为 idex 的数字已经在它应该存在的位置了,所以不必在进行排序)
//将index - 1 / index + 1 直接写为 idex
//导致程序进入了循环状态
Sort4(arr, left, index - 1);
Sort4(arr, index + 1, right);
}
void Text4()
{
int arr[] = { 9,5,2,7,4,1,3 };
int size = sizeof(arr) / sizeof(arr[0]);
Print4(arr, size);
Sort4(arr, 0, size - 1);
Print4(arr, size);
}
//////////////////////////////////////////////////////////////////////////////////
//6.选择排序
#pragma once
#include<stdio.h>
void Swap2(int* a, int* b)
{
int i = *a;
*a = *b;
*b = i;
}
//9, 5, 2, 7, 4, 1
void Select(int arr[], int size)
{
for (int i = 0; i < size; i++) {
// 有序 [size - i, size - 1]
// 无序 [0, size - 1 - i]
int max = 0;
// 要查找整个无序区间的最大值的下标
int j = 0;
for (j; j <= size - 1 - i; j++) {
if (arr[j] >= arr[max]) {
max = j;
}
}
// maxIdx 记录着无序区间部分最大的数的下标
// 和无序区间的最后一个位置的数进行交换
Swap2(&arr[max], &arr[size - 1 - i]);
}
//在这里用while也可以
//while (size > 0)
//{
// int max = 0;
// for (int j = 0; j < size; j++)
// {
// if (arr[max] < arr[j])
// {
// max = j;
// }
// }
// Swap2(&arr[max], &arr[size - 1]);
// size--;
//}
}
void Print2(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void Text2()
{
int arr[] = { 199,84,3,77,4,6,2 };
int size = sizeof(arr) / sizeof(arr[0]);
Print2(arr, size);
Select(arr, size);
Print2(arr, size);
}
//////////////////////////////////////////////////////////////////////////////////
//7.希尔排序
#pragma once
#include<stdio.h>
void Swap6(int* a, int* b)
{
int c = *a;
*a = *b;
*b = c;
}
void Print6(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
//希尔排序
//思路:
//把记录按下标的一定增量分组,对每组使用直接插入排序算法排序。
//随着增量逐渐减少,每组包含的关键词越来越多。
//当增量减至1时,整个文件恰被分成一组,算法便终止。
void InsertSortWithGap(int array[], int size, int gap) {
for (int i = 0; i < size; i++) {
int key = array[i];
int j;
for (j = i - gap; j >= 0 && array[j] > key; j -= gap) {
array[j + gap] = array[j];
}
array[j + gap] = key;
}
}
void Sort6(int array[], int size) {
int gap = size;
while (1) {
gap = gap / 3 + 1;
// gap = gap / 2;
InsertSortWithGap(array, size, gap);
if (gap == 1) {
break;
}
}
}
void Text6()
{
int arr[] = { 9,5,2,7,4,1,3 };
int size = sizeof(arr) / sizeof(arr[0]);
Print6(arr, size);
Sort6(arr, size);
Print6(arr, size);
}
////////////////////////////////////////////////////////////////////////////////