选择排序
1. 简单选择排序
-
基本思想
进行n-1趟,每趟选出未排序的最小值与第i个元素交换。 -
例子
-
代码实现
void selectSort(int list[])
{
int n=sizeof(list)/sizeof(int);
for (int i = 0; i < n - 1; i++)
{
int k = i;
for (int j = i + 1; j < n; j++)
{
if (list[j] < list[k])
k = j;
}
if (k != i)
{
int temp = list[i];
list[i] = list[k];
list[k] = temp;
}
}
}
- 算法分析
时间复杂度:O(n²)
空间复杂度:O(1)
稳定性:不稳定
2. 堆排序
进行堆排序时,我们得先明白几个概念:
堆:堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:
Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]
或Key[i]>=Key[2i+1]&&key>=key[2i+2]
大根堆:每个节点的值都大于或者等于它的左右子节点的值。如下图:
小根堆:每个节点的值都小于或者等于它的左右子节点的值。如下图:
这里堆排序使用的是大根堆,所以必须明白大根堆的概念。
- 基本思想
(1)将序列r[0…n-1] 建成大根堆,则r[n-1]为关键字最大的记录,交换r[0]和r[n-1]。
(2)将r[0…n-2]重新调整为大根堆,则r[n-2]为关键字次大的记录,交换r[0]和r[n-2] 。
(3)循环n-1次,直到交换了r[0]和r[1]为止,得到了一个非递减的有序序列r[0…n-1]。
总的来说,就是先把无序序列建成大根堆,根节点为最大值,就可以跟无序序列的最后一个元素交换,使最后一个节点有序。再重新将无序序列建成大根堆,重复以上步骤直到有序。 - 代码实现
void headSort(vector<int> &list)
{
int len=list.size();
for (int i = len / 2 - 1; i > 0; i--)//将无序数组变为大根堆
{
headMax(list, i,len);
}
for (int i = len - 1; i > 0; i--)
{
//根节点为最大值,排到后面无序数组的最后一个元素
int temp = list[i];
list[i] = list[0];
list[0] = temp;
//重新调整为大根堆
len--;
headMax(list, 0, len);
}
}
void headMax(vector<int> &list, int p,int len)
{
int left = 2 * p + 1;
int right = 2 * p + 2;
int max = p;
if (left<len&&list[left]>list[max])
max = left;
if (right<len&&list[right]>list[max])
max = right;
if (max != p)
{
int temp = list[max];
list[max] = list[p];
list[p] = temp;
headMax(list, max, len);//交换之后子节点的值发生改变,如果该子节点存在节点,则需要重新调整
}
}
- 算法分析
时间复杂度:O(nlog2n)
空间复杂度:O(1)
稳 定 性:不稳定,适用于n 较大的情况。