常见排序算法之选择排序

wKiom1e4VhPCEcFTAAEKCEW4XWs985.png

wKiom1e4VhPhRUAXAAENhyAGQkY878.jpg

1.直接选择排序数组

直接选择排序和直接插入排序相似,都将数据分为有序区和无序区,所不一样的是直接插入排序是将无序区的第一个元素直接插入到有序区以造成一个更大的有序区,而直接选择排序是从无序区选一个最小的元素直接放到有序区的最后。ide

设数组为a[0…n-1]。优化

1.      初始时,数组全为无序区为a[0..n-1]。令i=0spa

2.      在无序区a[i…n-1]中选取一个最小的元素,将其与a[i]交换。交换以后a[0…i]就造成了一个有序区。orm

3.      i++并重复第二步直到i==n-1。排序完成排序

这里直接给出一种比较优化的直接选择排序,每次遍历选出最大值和最小值
it

void SelectSort(int* a, size_t n)  //选择排序优化版
{
	assert(a);

	for (int left = 0, right = n - 1; left < right; ++left, --right)
	{
		int min = left;
		int max = right;

		for (int i = left; i <= right; ++i)
		{
			if (a[i] < a[min])
				min = i;
			else if (a[i] > a[max])
				max = i;
		}

		if (min != left)
		{
			std::swap(a[min], a[left]);

			if (max == left)
			{
				max = min;
			}
		}
		if (max != right)
		{
			std::swap(a[max], a[right]);
		}

	}
}

2.堆排序
io

将待排序的数组创建一个大堆,每次将堆顶的元素取出放在数组的最后一个位置上,再对数组的长度减1,而后对堆进行调整,使之仍然是一个大堆,直到堆的长度为1,将此元素放在数组的起始位置,排序完成。class

void AdjustDown(int* a, size_t size, size_t root)
{
	assert(a);

	int child = root * 2 + 1;
	while (child < size)
	{
		if (child+1 < size && a[child + 1] > a[child])
		{
			++child;
		}
		if (a[child] > a[root])
		{
			std::swap(a[child], a[root]);
			root = child;
			child = root * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapSort(int* a, size_t n)
{
	assert(a);
	for (int i = (n-2)/2; i >=0 ; --i)
	{
		AdjustDown(a, n, i);  //建(大)堆
	}

	for (int i = n - 1; i > 0; --i)  //这样写比较好
	{
		std::swap(a[0], a[i]);
		AdjustDown(a, i - 1, 0);
	}

}

j_0004.gifj_0004.gifj_0004.gifj_0004.gifj_0004.gifj_0004.gifj_0004.gifj_0004.gifj_0004.gifj_0004.gifj_0004.gif

相关文章
相关标签/搜索