//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(" "); } //冒泡排序 //思想: //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(" "); } 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(" "); } 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(" "); } //归并排序 //思想: //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(" "); } //挖坑 //思想: //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(" "); } 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(" "); } //希尔排序 //思路: //把记录按下标的一定增量分组,对每组使用直接插入排序算法排序。 //随着增量逐渐减少,每组包含的关键词越来越多。 //当增量减至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); } ////////////////////////////////////////////////////////////////////////////////