常见的排序——选择排序(直接选择排序和堆排序)

选择排序选择排序又分为直接选择排序和堆排序,这里我们来写升序的排序。
直接选择排序其基本思想,每一次从待排序的数组元素中选出最小(或最大)的一个元素,存放在序列的起始,然后遍历比较每次将最小(最大)的放在前面直到待排序的数据排完。

//交换值
void Swap(int *a, int *b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
void SelectSort(int array[], int size)
{
	for (int i = 0; i < size; i++){
		int min = i;
		for (int j = i + 1; j < size; j++){
			if (array[j] < min){
				min = j;
			}
		}
		Swap(&array[i], &array[min]);
	}
}

直接选择排序的特性总结:时间复杂度O(n*n),空间复杂度O(1),是一个不稳定的排序。选择排序效率特别低。
堆排序其基本思想:先建立一个大堆(小堆),然后进入循环,每次将堆顶元素与数组中最后一个元素进行交换后进行向下调整。直到循环到根节点为止。需要注意的是排升序建大堆,排降序建小堆。

//交换值
void Swap(int *a, int *b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
//向下调整法
//思路:如果[root]所在的结点已经是叶子节点调整就结束,
//找到左右孩子中最小的与其交换,min=root,从新进入循环
void AdjustDown(int array[],int size,int root)
{
	while (1){
		int left = 2 * root + 1;
		//这里判一下叶子节点有没有出界,然后左孩子超出范围其右孩子一定也超出范围
		if (left >=size){
			return;
		}
		int right = 2 * root + 2;
		int max = left;
		//比较左右孩子节点那个大
		if (right<size&&array[right]>array[left]){
			max = right;
		}
		//比较左右孩子中最大的和根节点
		if (array[root] > array[max]){
			return;
		}
		Swap(&array[root], &array[max]);
		root = max;
	}
}
//创建一个大堆
void CreateHeap(int array[], int size)
{
	//这里size-2,为数组中最后一个节点size-1,的双亲节点
	for (int i = (size - 2) / 2; i >= 0;i--){
		AdjustDown(array, size, i);
	}
}
//堆排序
void HeapSort(int array[], int size)
{
	CreateHeap(array, size);
	for (int i = 0; i < size; i++){
		Swap(&array[size - 1 - i], &array[0]);
		AdjustDown(array, size - i - 1,0);
	}
}
void SelectSort(int array[], int size)
{
	for (int i = 0; i < size; i++){
		int min = i;
		for (int j = i + 1; j < size; j++){
			if (array[j] < min){
				min = j;
			}
		}
		Swap(&array[i], &array[min]);
	}
} 

堆排序的特性总结:时间复杂度O(n*logn),空间复杂度O(1),是一个不稳定的排序。堆排序使用堆选数其效率更高了。

猜你喜欢

转载自blog.csdn.net/weixin_43198968/article/details/88550660
今日推荐