选择排序
基本思想: 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
直接选择排序
- 在元素集合 arr[0]—ar[n] 中选择关键码最大(最小)的元素。
- 若它不是这组元素中的最后一个元素(第一个元素),则将它与这组元素中的最后一个(第一个)元素交换。
- 在剩余的 arr[0]—arr[n-1] 中选择关键码最大(最小)的元素,重复上述步骤,直到集合剩余一个元素。
以数组 int arr[] = { 9, 6, 3, 6, 2, 7, 5, 8, 1 } 举例(升序):
第一步,遍历 arr[0]–arr[8] ,找到最小值的下标min=8,arr[0]与arr[8]值交换
第二步,遍历 arr[1]–arr[8] ,找到最小值的下标min=2,arr[1]与arr[2]值交换
…
重复上述步骤,直到集合剩余一个元素
代码演示:
int arr[] = { 9, 6, 3, 6, 2, 7, 5, 8, 1 };
//进行排序
for (int i =0;i<sizeof(arr)/sizeof(int)-1;i++)
{
int leght = i;//定位最左的未排序的下标
int min = i;//可移动查找的下标
int j = i;//最左的未排序的下标随着排序变动
for (j = leght; j < sizeof(arr) / sizeof(int); j++)
{
//找未排序的最小值
if (arr[min] > arr[j])
{
min = j;
}
}
//交换值
int tmp = arr[min];
arr[min] = arr[leght];
arr[leght] = tmp;
}
return 0;
这里,对二叉树进行了优化: 遍历一次查询最大值和最小值。感兴趣的同学可以了解下:
int main()
{
//举例的是特殊形式的数组
int arr[] = { 9, 6, 3, 6, 2, 7, 5, 8, 1 };
int leght = 0;
int right = sizeof(arr)/sizeof(int)-1;
//排序左侧的数和右侧的数
while (leght < right)
{
//从leght 开始比较
int min = leght;
int max = leght;
for (int j = leght; j <= right; j++)
{
//找最小值的下标
if (arr[min] > arr[j])
{
min = j;
}
//找最大值的下标
if (arr[max] < arr[j])
{
max = j;
}
}
//小的值放左侧
int tmp = arr[min];
arr[min] = arr[leght];
arr[leght] = tmp;
//特殊条件,max==leght,会出现最小值再数组的右边
if (max == leght)
{
max = min;
}
//大的值放右侧
tmp = arr[max];
arr[max] = arr[right];
arr[right] = tmp;
leght++;
right--;
}
return 0;
}
堆排序
堆排序是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是,排升序建大堆,排降序建小堆
堆排序需要具有二叉树的相关知识
未学过二叉树和堆的点击此链接
以数组 int arr[] = { 5, 17, 4, 20, 16, 3 };举例:
- 先把数组变成大堆
- 把 arr[0] 和 arr[n] 交换值,再用向下调整算法
- 把 arr[1] 和 arr[n-1] 交换值,再用向下调整算法
- …
代码演示:
//值交换函数
void Swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int main()
{
int arr[] = { 5, 17, 4, 20, 16, 3 };
//在原数组内用向上调整法->大堆
for (int i = 1; i < sizeof(arr) / sizeof(int); i++)
{
int child = i;
int parent = (i - 1) / 2;
while (child > 0)
{
if (arr[child] > arr[parent])
{
Swap(&arr[child], &arr[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
//排序
for (int j = sizeof(arr) / sizeof(int) - 1; j > 0; j--)
{
//从后往前排,把最大值放数组尾部
Swap(&arr[0], &arr[j]);
//向下调算法
int parent = 0;
int child = 0 * 2 + 1;//假设左孩子大
while (child < j)//左孩子要在未排序的范围内
{
//右孩子要在未排序的范围内
if (child + 1 < j-1 && arr[child] < arr[child+1])
{
//假设不成立就换成右孩子
child++;
}
//父子交换值
if (arr[child] > arr[parent])
{
Swap(&arr[child], &arr[parent]);
//父子换下标
parent = child;
child = parent*2 + 1;//继续假设左孩子大
}
else
{
break;
}
}
}
return 0;
}