国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

DS八大排序之直接選擇排序和堆排序

這篇具有很好參考價值的文章主要介紹了DS八大排序之直接選擇排序和堆排序。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言

上一期我們已經(jīng)介紹了,排序、為什么要有排序以及排序在實際生活中的應(yīng)用。并且介紹并實現(xiàn)了直接插入排序和它的優(yōu)化即希爾排序~!本期我們再來學習一組排序 ---- "選擇排序"即直接選擇排序和堆排序~!

本期內(nèi)容介紹

直接選擇排序

堆排序

選擇排序的基本思想

每次從待排序的數(shù)據(jù)元素的序列中選出最小或最大的一個元素存放在當前序列的起始位置,直到將全部待排序的數(shù)據(jù)元素排完。

直接選擇排序

在元素集合a[i].....a[n-1]中,選擇一個最大最小的數(shù)據(jù),如果他不是這個序列中的最后一個第一個,則該序列中的最后一個第一個進行交換,將剩余的元素重復上述操作,直到序列的元素只有一個則結(jié)束!

OK,舉個栗子畫個圖(這里是以升序距離的):

DS八大排序之直接選擇排序和堆排序,DS初階,排序算法,數(shù)據(jù)結(jié)構(gòu),算法

OK,直接選擇排序的過程就是這樣的,下面我們來實現(xiàn)一下:還是和以前一樣,先寫單趟再來改造整體:

單趟

int left = begin;//當前序列的最左端
int min = begin;//最小的元素的下標
for (int i = begin; i < n; i++)
{
	if (a[min] > a[i])
		min = i;
}

Swap(&a[left], &a[min]);//最左端的元素與當前序列中最小的元素交換

整體

直接選擇排序改造整體也很簡單,只需要,讓每個元素都重復單趟即可~!

void SelectSort(int* a, int n)
{
	for (int begin = 0; begin < n; begin++)
	{
		int left = begin;//當前序列的最左端
		int min = begin;//最小的元素的下標
		for (int i = begin; i < n; i++)
		{
			if (a[min] > a[i])
				min = i;
		}

		Swap(&a[left], &a[min]);//最左端的元素與當前序列中最小的元素交換
	}
}

OK,測試一下:

DS八大排序之直接選擇排序和堆排序,DS初階,排序算法,數(shù)據(jù)結(jié)構(gòu),算法

OK,沒有問題。這樣寫實每次找到當前序列中最小的一個,然后與最左端(升序)交換,我們其實可以對他進行一個小優(yōu)化的--->每次找到當前序列中的兩個元素(一個最小,一個最大),最小的與當前序列的最左端交換,最大與當前序列的最右端交換~!

OK,還是先寫單趟,在改造多趟:

單趟

int min = begin, max = begin;
for (int i = begin + 1; i <= right; i++)
{
	if (a[min] > a[i])
		min = i;//選出最小

	if (a[max] < a[i])
		max = i;//選出最大
}

Swap(&a[begin], &a[min]);//最小與左端交換
Swap(&a[right], &a[max]);//最大與右端交換

整體

void SelectSort(int* a, int n)
{
	int begin = 0, right = n - 1;
	while (begin < right)
	{
		int min = begin, max = begin;
		for (int i = begin + 1; i <= right; i++)
		{
			if (a[min] > a[i])
				min = i;

			if (a[max] < a[i])
				max = i;
		}

		Swap(&a[begin], &a[min]);
		Swap(&a[right], &a[max]);
		++begin;
		--right;
	}
}

這就是一次選出兩個的整體。OK,我們來個栗子測試一下:

DS八大排序之直接選擇排序和堆排序,DS初階,排序算法,數(shù)據(jù)結(jié)構(gòu),算法

怎么沒有實現(xiàn)排序呢?是我們的思想有問題???OK,遇事不慌,調(diào)試走起:

DS八大排序之直接選擇排序和堆排序,DS初階,排序算法,數(shù)據(jù)結(jié)構(gòu),算法

這是調(diào)試找到的第一次最大和最小的元素的下標~!然后下來就是最小與左端交換,最大與右端交換,但此時最大恰好在最左端,一執(zhí)行最小與最左端交換后在在執(zhí)行在最大與最右交換時發(fā)現(xiàn)最大的已經(jīng)不在原來的位置了~!這就導致了上述的亂序!

解決方案:在交換完最小與最左端后,判斷一下最大的位置,如果最大的是在最左端,則此時最大值應(yīng)該被換到了最小值的位置,因此,我們只需要調(diào)整一下最大值是在最小值的位置即可,即max = min~!

void SelectSort(int* a, int n)
{
	int left = 0, right = n - 1;
	while (left < right)
	{
		int min = left, max = left;
		for (int i = left + 1; i <= right; i++)
		{
			if (a[min] > a[i])
				min = i;

			if (a[max] < a[i])
				max = i;
		}

		Swap(&a[left], &a[min]);
		if (max == left)
			max = min;
		Swap(&a[right], &a[max]);
		++left;
		--right;
	}
}

再來測試一下:

DS八大排序之直接選擇排序和堆排序,DS初階,排序算法,數(shù)據(jù)結(jié)構(gòu),算法

OK,沒有問題了~!

復雜度分析

時間復雜度:O(N^2)

單趟無論選擇一個還是選擇兩個,都得遍歷一遍,復雜度為O(N),整體還得遍歷一遍O(N)

空間復雜度:O(1)

堆排序

堆排序其實在前面的二叉樹堆那里已經(jīng)介紹并實現(xiàn)過了,這來就等于回顧式的再過一遍~!如果想了解堆這種他是具體咋搞的請點擊:二叉樹的實現(xiàn)

堆排序(Heapsort)是指利用堆,這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計的一種排序算法,它是選擇排序的一種。它是通過堆來進行選擇數(shù)據(jù)進行實現(xiàn)排序的。

他既然是借助堆來實現(xiàn)的那得有堆,即要建堆。這里有兩種建堆的方式:向上調(diào)整建堆+向下調(diào)整排序,向下調(diào)整建堆+向下調(diào)整排序!

他排序是采用刪除的思想,把最大或最小的換到最后,然后對前N-i(i=1,2,3...n)個進行向下調(diào)整!
注意:升序建大堆,降序建小堆

OK,舉個排序的例子:

DS八大排序之直接選擇排序和堆排序,DS初階,排序算法,數(shù)據(jù)結(jié)構(gòu),算法

向上調(diào)整建堆

void HeapSort(HPDataType* a, int n)
{
	//向上調(diào)整建堆
	//O(N*lgN)
	for (int i = 1; i < n; i++)
	{
		AdjustUp(a, i);
	}
 
	//向下調(diào)整排序
	//O(N*lgN)
	int end = n - 1;
	while (end)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		--end;
	}
}

這里的向上調(diào)整建堆和上面堆的插入是一個思路!時間復雜度是O(lgN*N),向下調(diào)整排序的時間復雜度是:O(N*lgN)---->有n個元素,每排好一個一下下標,也就是上面的刪除的思路!

向下調(diào)整建堆

void HeapSort(HPDataType* a, int n)
{
	//向下調(diào)整建堆
	//O(N)
	for (int i = (n - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, n, i);
	}
 
	//向下調(diào)整排序
	//O(N*lgN)
	int end = n - 1;
	while (end)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		--end;
	}
}

向下調(diào)整建堆,就是從倒數(shù)第一個元素的父節(jié)點開始向下調(diào)整為堆!這樣越往上層節(jié)點的左右子樹必定是堆!

DS八大排序之直接選擇排序和堆排序,DS初階,排序算法,數(shù)據(jù)結(jié)構(gòu),算法

OK,測試一下:

DS八大排序之直接選擇排序和堆排序,DS初階,排序算法,數(shù)據(jù)結(jié)構(gòu),算法

沒問題~!

復雜度分析

時間復雜度:O(N*logN)

向下調(diào)整和向上調(diào)整的時間復雜度都是O(logN)即最多調(diào)整高度次,但向上調(diào)整建堆是O(N*log)而向下調(diào)整建堆的O(N)如下圖~!刪除排序的時間復雜度是O(N*logN),所以綜合下來就是O(N*logN)

空間復雜度:O(1)

向下調(diào)整建堆時間復雜度推導

DS八大排序之直接選擇排序和堆排序,DS初階,排序算法,數(shù)據(jù)結(jié)構(gòu),算法

向上調(diào)整建堆時間復雜度推導

DS八大排序之直接選擇排序和堆排序,DS初階,排序算法,數(shù)據(jù)結(jié)構(gòu),算法

OK,本期分享就到這里,好兄弟,下期交換排序不見不散~!文章來源地址http://www.zghlxwxcb.cn/news/detail-761418.html

到了這里,關(guān)于DS八大排序之直接選擇排序和堆排序的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包