前排提醒:选择排序的实现因人而异,我只是给出一种自己习惯的
目录
一,选择排序
选择排序是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小和最大的两个元素,分别存放在序列的首位置和末尾置,然后再从剩余的未排序元素中寻找到最小和大元素,然后放到未排序序列的首位置和末尾置。以此类推,直到全部待排序的数据元素的个数为零。
1,单趟:
初始状态下,范围是0到numsSize-1,找到最小、最大元素分别对应的下标min_i,max_i,并使nums[left]与nums[min_i]两元素进行交换,以及nums[right]与nums[max_i]两元素进行交换
2,循环以及终止:
缩小范围直到left与right相遇,即两者之间没有元素了
3,特别注意以下这段代码的出现的位置以及意义
因为我们需要进行两次交换,在一种情况下第一次交换产生影响会对第二次交换产生副作用
这种情况就是left==max_i,以下的代码就是防范此种情况发生的修正
if (max_i == left)
{
max_i = min_i;
}
void Swap(int* x,int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
void SelectSort(int* nums, int numsSize)
{
int left = 0;
int right = numsSize - 1;
while (left < right)
{
int min_i = left;
int max_i = right;
for (int i = left; i <= right; i++)
{
min_i = nums[i] < nums[min_i] ? i : min_i;
max_i = nums[i] > nums[max_i] ? i : max_i;
}
Swap(&nums[left], &nums[min_i]);
if (max_i == left)
{
max_i = min_i;
}
Swap(&nums[right], &nums[max_i]);
left++;
right--;
}
}
二,堆排序
1,建堆,将数组建为大堆(找到尾元素的父节点,向前逐个进行向下调整)
2,交换首尾数据,再次向下调整
3,重复步骤2直到堆中只有一个元素
void HeapSort(int* nums, int numsSize)
{
for (int i = (numsSize - 2) / 2; i >= 0; i--)
{
AdjustDown(nums, numsSize, i);
}
int end = numsSize - 1;
while (end >= 0)
{
Swap(&nums[0], &nums[end]);
AdjustDown(nums, end, 0);
end--;
}
}
void Swap(int* x, int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
void AdjustDown(int* nums, int numsSize, int parent)
{
int child = parent * 2 + 1;
while (child < numsSize)
{
if (child + 1 < numsSize && nums[child + 1] > nums[child])
{
child += 1;
}
if (nums[child] > nums[parent])
{
Swap(&nums[child], &nums[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}