掌握七大排序(2)--- 选择排序,堆排序和冒泡排序

目录

      • 一. 选择排序
    • 1.基本思想:
    • 2. 代码展示:
    • 3. 改进版本:
    • 4.总结:
      • 二. 堆排序
    • 1.基本思想:
    • 2. 代码展示:
    • 3.总结:
      • 三. 冒泡排序
    • 1.基本思想:
    • 2. 代码展示:
    • 3. 总结:

一. 选择排序

1.基本思想:

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。
动图演示:

在元素集合array[i]–array[n-1]中选择关键码最大(小)的数据元素
若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
在剩余的array[i]–array[n-2](array[i+1]–array[n-1])集合中,重复上述步骤,直到集合剩余1个元素

2. 代码展示:

void SelectSort(int* a, int n)
{

	for (int i = 0; i < n - 1; i++)
	{
		int min = i;
		for (int j = i + 1; j < n; j++)
		{
			if (a[min] > a[j])
			{
				min = j;
			}
		}
		swap(&a[i], &a[min]);
	}
}

3. 改进版本:

我们可以一次从中选择出最大和最小值。即
第一次选出最小值放在a[0]处,最大值放在a[n-1]处
第二次选出最小值放在a[1]处,最大值放在a[n-2]处

直到两者相遇或超过

代码展示:

void SelectSort(int* a, int n)
{

	int begin = 0, end = n - 1;
	while (begin < end)
	{
		int mini = begin, maxi = begin;
		for (int i = begin + 1; i <= end; i++)
		{
			if (a[i] < a[mini])
				mini = i;
			if (a[i] > a[maxi])
				maxi = i;
		}
		swap(&a[begin], &a[mini]);
		if (maxi == begin)
		{
			maxi = mini;
		}
		swap(&a[end], &a[maxi]);
		begin++;
		end--;
	}
}

此处需注意:

		swap(&a[begin], &a[mini]);
		if (maxi == begin)
		{
			maxi = mini;
		}
		swap(&a[end], &a[maxi]);

为什么需要判断一下maxi是否等于begin呢?

我们举个例子:
我们对数据5,4,3,2,1进行排序,第一次找到最大值是5,maxi = 0,最小值是1,mini = 4;
我们进行swap交换,变成1,4,3,2,5.此时的maxi位置发生了移动,在进行第二次交换之前,我们需要修正一下maxi的值。

4.总结:

  1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1)
  4. 稳定性:不稳定

二. 堆排序

建议大家在学习堆排序前,如果不太了解堆,可以先学习一下堆,再来学习堆排序。
数据结构–堆

1.基本思想:

堆排序即利用堆的思想来进行排序,总共分为两个步骤:
1. 建堆:

升序:建大堆
降序:建小堆

2. 利用堆删除思想来进行排序
建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序。
以升序为例:
1.将第一个结点(所有元素中值最大的)与最后一个结点交换值,再对第一个结点进行向下调整,这样最大的数就到了最后面,我们只需要排前n-1个数。
2.再将第一个结点(次大的)与倒数第二个结点交换值,对第一个结点进行向下调整,以此类推。
掌握七大排序(2)--- 选择排序,堆排序和冒泡排序_第1张图片

2. 代码展示:

void HeapSort(HP* php)
{
	int end = php->size - 1;

	//升序建大堆
	while (end)
	{
		swap(&php->a[end], &php->a[0]);
		AdjustDown(php->a, end, 0);
		end--;
	}
}

void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child] > a[child + 1])
		{
			child++;
		}
		if (a[child] < a[parent])
		{
			swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}

3.总结:

  1. 堆排序使用堆来选数,效率就高了很多。
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(1)
  4. 稳定性:不稳定

三. 冒泡排序

1.基本思想:

以动图的形式展示:
掌握七大排序(2)--- 选择排序,堆排序和冒泡排序_第2张图片

2. 代码展示:

void BubbleSort(int* a, int n)
{
	for (int j = 0; j < n; j++)
	{
		int exchange = 0;
		for (int i = 0; i < n - 1 - j; i++)
		{
			if (a[i] > a[i + 1])
			{
				swap(&a[i], &a[i + 1]);
				exchange = 1;
			}
		}
		if (exchange == 0)
		{
			break;
		}
	}
}

3. 总结:

  1. 冒泡排序是一种非常容易理解的排序
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1)
  4. 稳定性:稳定

你可能感兴趣的:(数据结构,算法,排序算法,数据结构)