常見排序算法之選擇排序

wKiom1e4VhPCEcFTAAEKCEW4XWs985.png

wKiom1e4VhPhRUAXAAENhyAGQkY878.jpg

1.直接選擇排序

直接選擇排序和直接插入排序類似,都將數據分爲有序區和無序區,所不同的是直接插入排序是將無序區的第一個元素直接插入到有序區以形成一個更大的有序區,而直接選擇排序是從無序區選一個最小的元素直接放到有序區的最後。

設數組爲a[0…n-1]。

1.      初始時,數組全爲無序區爲a[0..n-1]。令i=0

2.      在無序區a[i…n-1]中選取一個最小的元素,將其與a[i]交換。交換之後a[0…i]就形成了一個有序區。

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

這裏直接給出一種比較優化的直接選擇排序,每次遍歷選出最大值和最小值

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.堆排序

將待排序的數組建立一個大堆,每次將堆頂的元素取出放在數組的最後一個位置上,再對數組的長度減1,然後對堆進行調整,使之仍然是一個大堆,直到堆的長度爲1,將此元素放在數組的起始位置,排序完成。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章