选择排序:每一次从待排序元素中选择一个最大的或最小的元素,顺序放在已排好序的数列最后,直到整个数列全部有序。
选择排序优化:
同时选最大和最小值,每一趟遍历标记最大最小值的位置,然后分别交换到区间两端,再缩小区间重复此操作。
每次找到目标位置后用一个tmp保存最大值位置(或最小值位置)是为了防止在该位置的值被换走。比如:
//SelectSort
void SelectSort(int *array, size_t size)
{
assert(array);
int left = 0;
int right = size - 1;
while (left<right)
{
int min = left;
int max = left;
int tmp = 0;
for (size_t index = left + 1; index < right+1; ++index)
{
if (array[index] <= array[min])
{
min = index;
}
else if (array[index]>=array[max])
{
max = index;
}
}
tmp = array[max];
swap(array[left], array[min]);
if (array[max] != tmp)
{
swap(array[min], array[right]);
}
else
{
swap(array[max], array[right]);
}
++left;
--right;
}
}
堆排序:1、建堆;升序建大堆
2、堆头和最后一个叶子交换;
3、size–,重新向下调整
堆排序时间复杂度O(nlogn),即使有序也是O(nlogn)
所以堆排序不一定比选择排序优。
//HeapSort
void AdjustDown(int *array, size_t root, size_t size)
{
assert(array);
int child = 2 * root + 1;
while (child<size)
{
if (child + 1 < size && array[child + 1] > array[child])
{
child++;
}
if (array[child] > array[root])
{
swap(array[child], array[root]);
root = child;
child = 2*root + 1;
}
else
{
break;
}
}
}
void HeapSort(int *array, size_t size)
{
assert(array);
//1、从最后一个非叶子节点开始 建堆
int root = (size - 2) / 2;
while (root >= 0)
{
AdjustDown(array, root, size);
root--;
}
//2、堆头和最后一个元素交换,“剔除”最后一个(即size--),向下调整
for (size_t index = size - 1; index > 0; --index)
{
swap(array[0], array[index]);
AdjustDown(array, 0, index);
}
}