- #pragma once
- #include
-
- void PrintArray(int* a, int n);
-
- void InsertSort(int* a, int n);
- void ShellSort(int* a, int n);
- void BubbleSort(int* a, int n);
- void HeapSort(int* a, int n);
- void SelectSort(int* a, int n);
准备工作
- #include"Sort.h"
-
- void PrintArray(int* a, int n)
- {
- for (int i = 0; i < n; i++)
- {
- printf("%d ", a[i]);
- }
- printf("\n");
- }
-
- void Swap(int* x, int* y)
- {
- int tmp = *x;
- *x = *y;
- *y = tmp;
- }
-
-
- void InsertSort(int* a, int n)
- {
- // [0,end]有序,把end+1位置的插入到前序序列
- // 控制[0,end+1]有序
- for (size_t i = 0; i < n - 1; i++)
- {
- int end = i;
- int tmp = a[end + 1];
- while (end >= 0)
- {
- if (tmp < a[end])
- {
- a[end + 1] = a[end];
- }
- else
- {
- break;
- }
-
- --end;
- }
-
- a[end + 1] = tmp;
- }
- }
void InsertSort(int* a, int n)
:这是一个名为InsertSort
的函数,它接受一个整型数组指针a
和一个整数n
作为参数,表示要排序的数组和数组的长度。
for (size_t i = 0; i < n - 1; i++)
:使用for
循环遍历数组,从第一个元素开始直到倒数第二个元素。
int end = i;
:在每次循环开始时,将end
初始化为当前循环的索引i
。
int tmp = a[end + 1];
:将下一个位置的元素保存在tmp
变量中,用于后续的插入操作。
while (end >= 0)
:进入一个while
循环,该循环会从当前位置向前遍历,直到找到合适的位置插入tmp
。
if (tmp < a[end])
:如果tmp
比当前位置的元素小,则将当前位置的元素后移一位。
else
:否则,跳出循环,表示找到了tmp
应该插入的位置。
a[end + 1] = tmp;
:将tmp
插入到找到的位置后面,完成一次插入操作。
- void ShellSort(int* a, int n)
- {
- int gap = n;
- while (gap > 1)
- {
- //gap = gap / 2;
- gap = gap / 3 + 1;
-
- for (int i = 0; i < n - gap; ++i)
- {
- int end = i;
- int tmp = a[end + gap];
- while (end >= 0)
- {
- if (tmp < a[end])
- {
- a[end + gap] = a[end];
- end -= gap;
- }
- else
- {
- break;
- }
- }
- a[end + gap] = tmp;
- }
- }
- }
void ShellSort(int* a, int n)
:这是一个名为ShellSort
的函数,接受一个整型数组指针a
和一个整数n
作为参数,表示要排序的数组和数组的长度。
int gap = n;
:初始化间隔gap
为数组的长度n
。
while (gap > 1)
:进入一个while
循环,当间隔大于1时执行排序算法。
gap = gap / 3 + 1;
:根据希尔排序的间隔序列选择规则,更新间隔gap
。通常选择gap = gap / 3 + 1。
for (int i = 0; i < n - gap; ++i)
:使用for
循环遍历数组,每次以间隔gap
对数组进行分组。
int end = i;
:在每次循环开始时,将end
初始化为当前循环的索引i
。
int tmp = a[end + gap];
:将当前位置往后间隔gap
的元素保存在tmp
变量中,用于后续的插入操作。
while (end >= 0)
:进入一个while
循环,该循环会从当前位置向前遍历,直到找到合适的位置插入tmp
。
if (tmp < a[end])
:如果tmp
比当前位置的元素小,则将当前位置的元素后移一个间隔gap
。
else
:否则,跳出循环,表示找到了tmp
应该插入的位置。
a[end + gap] = tmp;
:将tmp
插入到找到的位置后面,完成一次插入操作。
循环结束后,缩小间隔gap
,继续进行下一轮的排序操作,直到间隔为1时完成整个排序过程。
希尔
- void BubbleSort(int* a, int n)
- {
- for (size_t j = 0; j < n; j++)
- {
- int exchange = 0;
- for (size_t i = 1; i < n-j; i++)
- {
- if (a[i - 1] > a[i])
- {
- Swap(&a[i - 1], &a[i]);
- exchange = 1;
- }
- }
-
- if (exchange == 0)
- {
- break;
- }
- }
- }
void BubbleSort(int* a, int n)
:这是一个名为BubbleSort
的函数,接受一个整型数组指针a
和一个整数n
作为参数,表示要排序的数组和数组的长度。
for (size_t j = 0; j < n; j++)
:外层循环,控制需要进行多少轮冒泡排序,每轮将一个最大的元素移动到正确的位置。
int exchange = 0;
:用于标记在当前轮冒泡排序中是否发生过元素交换,若没有发生交换则表示数组已经有序,可以提前结束排序。
for (size_t i = 1; i < n-j; i++)
:内层循环,从第一个元素开始向后比较相邻的元素并进行交换。
if (a[i - 1] > a[i])
:如果前一个元素大于后一个元素,则交换它们的位置。
Swap(&a[i - 1], &a[i]);
:调用Swap
函数来交换两个元素的位置。
exchange = 1;
:标记发生了元素交换。
if (exchange == 0)
:如果在一轮冒泡排序中没有发生任何交换,说明数组已经有序,可以提前结束排序。
break;
:跳出外层循环,提前结束排序。
- void AdjustDown(int* a, int n, int parent)
- {
- int child = parent * 2 + 1;
- while (child < n)
- {
- // 找出小的那个孩子
- if (child + 1 < n && a[child + 1] > a[child])
- {
- ++child;
- }
-
- if (a[child] > a[parent])
- {
- Swap(&a[child], &a[parent]);
- // 继续往下调整
- parent = child;
- child = parent * 2 + 1;
- }
- else
- {
- break;
- }
- }
- }
-
- void HeapSort(int* a, int n)
- {
- // 向下调整建堆
- // O(N)
- for (int i = (n - 1 - 1) / 2; i >= 0; i--)
- {
- AdjustDown(a, n, i);
- }
-
- // O(N*logN)
- int end = n - 1;
- while (end > 0)
- {
- Swap(&a[0], &a[end]);
- AdjustDown(a, end, 0);
- --end;
- }
- }
void AdjustDown(int* a, int n, int parent)
:这是一个名为AdjustDown
的函数,用于向下调整堆。接受一个整型数组指针a
,数组长度n
和父节点索引parent
作为参数。
int child = parent * 2 + 1;
:计算父节点parent
的左孩子节点索引。
while (child < n)
:进入一个while
循环,循环条件是孩子节点索引小于数组长度。
if (child + 1 < n && a[child + 1] > a[child])
:如果右孩子存在且比左孩子大,则选择右孩子作为较小的孩子。
if (a[child] > a[parent])
:如果较小的孩子比父节点大,则交换父节点和孩子节点的值,并继续向下调整。
Swap(&a[child], &a[parent]);
:调用Swap
函数来交换父节点和孩子节点的值。
parent = child;
:更新父节点为当前孩子节点。
child = parent * 2 + 1;
:更新孩子节点为新的父节点的左孩子。
else
:如果孩子节点比父节点小或相等,则跳出循环,调整结束。
void HeapSort(int* a, int n)
:这是一个名为HeapSort
的函数,用于实现堆排序算法。接受一个整型数组指针a
和数组长度n
作为参数。
for (int i = (n - 1 - 1) / 2; i >= 0; i--)
:建立初始堆,从最后一个非叶子节点开始,向上逐个调整节点,保证每个节点都满足堆的性质。
AdjustDown(a, n, i);
:调用AdjustDown
函数进行向下调整。
int end = n - 1;
:初始化堆的末尾位置。
while (end > 0)
:进入一个while
循环,直到堆中只剩一个元素。
Swap(&a[0], &a[end]);
:将堆顶元素(最大值)与当前末尾元素交换。
AdjustDown(a, end, 0);
:调整交换后的堆顶元素,重新使堆满足堆的性质。
--end;
:缩小堆的范围,继续下一轮排序。
- void SelectSort(int* a, int n)
- {
- int begin = 0, end = n - 1;
-
- while (begin < end)
- {
- // [begin, end]
- int mini = begin, maxi = begin;
- for (int i = begin+1; i <= end; i++)
- {
- if (a[i] > a[maxi])
- {
- maxi = i;
- }
-
- if (a[i] < a[mini])
- {
- mini = i;
- }
- }
-
- Swap(&a[begin], &a[mini]);
- // max如果被换走了,修正一下
- if (maxi == begin)
- {
- maxi = mini;
- }
-
- Swap(&a[end], &a[maxi]);
-
- ++begin;
- --end;
- }
- }
void SelectSort(int* a, int n)
:这是一个名为SelectSort
的函数,接受一个整型数组指针a
和一个整数n
作为参数,表示要排序的数组和数组的长度。
int begin = 0, end = n - 1;
:初始化begin
为0,end
为数组长度减1,表示当前待排序部分的起始和结束位置。
while (begin < end)
:进入一个while
循环,循环条件是begin
小于end
,表示还有未排序的元素。
int mini = begin, maxi = begin;
:初始化最小值索引mini
和最大值索引maxi
为begin
,用于记录待排序部分中的最小值和最大值。
for (int i = begin+1; i <= end; i++)
:遍历待排序部分,查找最小值和最大值的索引。
if (a[i] > a[maxi])
:如果当前元素大于最大值元素,则更新最大值索引maxi
为当前元素索引i
。
if (a[i] < a[mini])
:如果当前元素小于最小值元素,则更新最小值索引mini
为当前元素索引i
。
Swap(&a[begin], &a[mini]);
:交换最小值元素和当前待排序部分的第一个元素。
if (maxi == begin)
:如果最大值索引maxi
等于begin
,说明最大值元素已经被换到最小值的位置,需要更新maxi
为最小值索引mini
。
Swap(&a[end], &a[maxi]);
:交换最大值元素和当前待排序部分的最后一个元素。
++begin;
:增加begin
指向下一个待排序元素。
--end;
:减少end
指向下一个待排序元素,同时缩小待排序部分的范围。