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

[數(shù)據(jù)結(jié)構(gòu) -- 手撕排序算法第七篇] 遞歸實(shí)現(xiàn)歸并排序

這篇具有很好參考價(jià)值的文章主要介紹了[數(shù)據(jù)結(jié)構(gòu) -- 手撕排序算法第七篇] 遞歸實(shí)現(xiàn)歸并排序。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

目錄

1、歸并的思想

2、歸并排序的思想

2.1 基本思想

2.2 圖解分析

3、歸并排序遞歸版本代碼實(shí)現(xiàn)

3.1 代碼解析

3.2 注意事項(xiàng)

3.2.1錯(cuò)誤劃分:[begin, mid-1],[mid, end]

3.2.2 正確劃分:[begin, mid], [mid+1, end]

4、歸并排序的測(cè)試

5、時(shí)間復(fù)雜度、空間復(fù)雜度分析

5.1 時(shí)間復(fù)雜度

5.2 空間復(fù)雜度


1、歸并的思想

這是我們第二次了解歸并的思想了,第一次在我們之前的鏈表oj題里面,合并兩個(gè)有序鏈表,我們當(dāng)時(shí)解題的思想就是歸并的思想。

我們這次來(lái)系統(tǒng)的學(xué)習(xí)一下歸并的思想(本篇以升序?yàn)槔归_(kāi)):

歸并兩個(gè)數(shù)組(鏈表)時(shí),我們使用兩個(gè)指針指向不同的數(shù)組首元素,控制并遍歷兩個(gè)數(shù)組,比較兩個(gè)指針指向的值,小的我們放入開(kāi)辟的臨時(shí)數(shù)組里面,然后讓指向小值的指針往后走一步,繼續(xù)比較。不斷去比,總有一個(gè)數(shù)組先被遍歷完,由于是有序數(shù)組,另外那個(gè)沒(méi)有被遍歷完的數(shù)組直接連接到臨時(shí)數(shù)組的后面就完成了排序。

我們畫圖來(lái)理解這個(gè)思想:

[數(shù)據(jù)結(jié)構(gòu) -- 手撕排序算法第七篇] 遞歸實(shí)現(xiàn)歸并排序,排序算法,排序算法,算法,數(shù)據(jù)結(jié)構(gòu),c語(yǔ)言

2、歸并排序的思想

2.1 基本思想

歸并排序是建立在歸并操作上的一種有效的排序算法。

1.歸并排序的思想是,將一個(gè)數(shù)組二分為左右兩個(gè)數(shù)組,然后對(duì)左右兩個(gè)數(shù)組繼續(xù)進(jìn)行二分,直到分為的子區(qū)間為一個(gè)數(shù)據(jù)的時(shí)候,這一個(gè)數(shù)據(jù)一定是有序的,便不再二分。

2.接下來(lái)就對(duì)左右兩個(gè)子區(qū)間進(jìn)行排序合并,不斷排序合并,最終就實(shí)現(xiàn)了整個(gè)數(shù)組的排序。

2.2 圖解分析

[數(shù)據(jù)結(jié)構(gòu) -- 手撕排序算法第七篇] 遞歸實(shí)現(xiàn)歸并排序,排序算法,排序算法,算法,數(shù)據(jù)結(jié)構(gòu),c語(yǔ)言

我們歸并的時(shí)候不是直接在原數(shù)組上就交換的,直接在原數(shù)組上操作會(huì)產(chǎn)生覆蓋,導(dǎo)致錯(cuò)誤。因此我們是malloc一個(gè)與原數(shù)組大小相同的空間tmp,將每次合并后的值拷貝到tmp中,合并一次拷貝一次,最中tmp數(shù)組為有序,再將tmp使用memcpy拷貝回原數(shù)組,再free(tmp) (防止內(nèi)存泄漏),整個(gè)排序就完成了。

3、歸并排序遞歸版本代碼實(shí)現(xiàn)

// 歸并排序遞歸實(shí)現(xiàn)
// 時(shí)間復(fù)雜度:O(N*logN)
// 空間復(fù)雜度:O(N + logN)
void _MergeSort(int* a, int begin, int end, int* tmp)
{
	if (begin >= end)
		return;

	int mid = (begin + end) / 2;
	//[begin, mid] [mid+1, end]
	_MergeSort(a, begin, mid, tmp);
	_MergeSort(a, mid+1, end, tmp);

	int begin1 = begin, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	int i = begin;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] <= a[begin2])
			tmp[i++] = a[begin1++];
		else
			tmp[i++] = a[begin2++];
	}

	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}

	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
	memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}
void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (NULL == tmp)
	{
		perror("malloc fail:");
		return;
	}
	_MergeSort(a, 0, n-1, tmp);
	free(tmp);
}
 

3.1 代碼解析

[數(shù)據(jù)結(jié)構(gòu) -- 手撕排序算法第七篇] 遞歸實(shí)現(xiàn)歸并排序,排序算法,排序算法,算法,數(shù)據(jù)結(jié)構(gòu),c語(yǔ)言

我們?cè)谶@一段使用了遞歸,遞歸的思想就是二分,將數(shù)組分為左右兩個(gè)區(qū)間,然后再對(duì)左右兩個(gè)區(qū)間繼續(xù)進(jìn)行二分,當(dāng) begin >= end 時(shí),就是最小的區(qū)間,然后我們就進(jìn)行排序+合并。

[數(shù)據(jù)結(jié)構(gòu) -- 手撕排序算法第七篇] 遞歸實(shí)現(xiàn)歸并排序,排序算法,排序算法,算法,數(shù)據(jù)結(jié)構(gòu),c語(yǔ)言

這一段就是排序+合并,我們對(duì)兩個(gè)子區(qū)間進(jìn)行排序+合并,思路就是我們歸并的思想。這里要注意,我們tmp的下標(biāo)是begin,因?yàn)槲覀冃枰獙⒚恳粚雍喜⒌闹迪确胚M(jìn)tmp中,然后再拷貝到原數(shù)組里,如果是0,拷貝回去的時(shí)候就會(huì)出現(xiàn)錯(cuò)誤。

3.2 注意事項(xiàng)

在劃分左右區(qū)間的時(shí)候一定是 [begin, mid],[mid+1, end],

不能是 [begin, mid-1],[mid, end]?。?!

這里很容易出錯(cuò),看著邏輯上沒(méi)問(wèn)題,但是在排序的時(shí)候就會(huì)出問(wèn)題。

3.2.1錯(cuò)誤劃分:[begin, mid-1],[mid, end]

[數(shù)據(jù)結(jié)構(gòu) -- 手撕排序算法第七篇] 遞歸實(shí)現(xiàn)歸并排序,排序算法,排序算法,算法,數(shù)據(jù)結(jié)構(gòu),c語(yǔ)言

3.2.2 正確劃分:[begin, mid], [mid+1, end]

[數(shù)據(jù)結(jié)構(gòu) -- 手撕排序算法第七篇] 遞歸實(shí)現(xiàn)歸并排序,排序算法,排序算法,算法,數(shù)據(jù)結(jié)構(gòu),c語(yǔ)言

總結(jié):造成第一種劃分死循環(huán)的原因是,當(dāng)我們 mid = begin+end/2 時(shí),計(jì)算器是向下取整的,所以一旦向下取整的時(shí)候,我們的區(qū)間就要包含mid這個(gè)值,這樣就會(huì)補(bǔ)上向下取整造成的舍去。

4、歸并排序的測(cè)試

void Print(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}
void _MergeSort(int* a, int begin, int end, int* tmp)
{
	if (begin >= end)
		return;

	int mid = (begin + end) / 2;
	// [begin, mid] [mid+1, end]
	_MergeSort(a, begin, mid, tmp);
	_MergeSort(a, mid + 1, end, tmp);

	int begin1 = begin, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	int i = begin;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] <= a[begin2])
			tmp[i++] = a[begin1++];
		else
			tmp[i++] = a[begin2++];
	}

	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}

	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
	memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}
void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (NULL == tmp)
	{
		perror("malloc fail:");
		return;
	}
	_MergeSort(a, 0, n - 1, tmp);

	free(tmp);
}
void test()
{
	int a[] = { 6,3,2,1,5,7,9 };
	Print(&a, sizeof(a) / sizeof(int));
	MergeSort(&a, sizeof(a) / sizeof(int) - 1);
	Print(&a, sizeof(a) / sizeof(int));
}
int main()
{
	test();

	return 0;
}
 

測(cè)試結(jié)果:

[數(shù)據(jù)結(jié)構(gòu) -- 手撕排序算法第七篇] 遞歸實(shí)現(xiàn)歸并排序,排序算法,排序算法,算法,數(shù)據(jù)結(jié)構(gòu),c語(yǔ)言

5、時(shí)間復(fù)雜度、空間復(fù)雜度分析

5.1 時(shí)間復(fù)雜度

歸并排序區(qū)間不斷二分,時(shí)間復(fù)雜度為O(logN);然后再合并,時(shí)間復(fù)雜度為O(N)。

整體的時(shí)間復(fù)雜度為o(N*logN)。

5.2 空間復(fù)雜度

因?yàn)槲覀冮_(kāi)辟了一個(gè)臨時(shí)空間用于排序,因此空間復(fù)雜度O(N)。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-573259.html

到了這里,關(guān)于[數(shù)據(jù)結(jié)構(gòu) -- 手撕排序算法第七篇] 遞歸實(shí)現(xiàn)歸并排序的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • 【數(shù)據(jù)結(jié)構(gòu)與算法篇】手撕八大排序算法之快排的非遞歸實(shí)現(xiàn)及遞歸版本優(yōu)化(三路劃分)

    【數(shù)據(jù)結(jié)構(gòu)與算法篇】手撕八大排序算法之快排的非遞歸實(shí)現(xiàn)及遞歸版本優(yōu)化(三路劃分)

    ???內(nèi)容專欄: 《數(shù)據(jù)結(jié)構(gòu)與算法篇》 ??本文概括: 利用數(shù)據(jù)結(jié)構(gòu)棧(Stack)來(lái)模擬遞歸,實(shí)現(xiàn)快排的非遞歸版本;遞歸版本測(cè)試OJ題時(shí),有大量重復(fù)元素樣例不能通過(guò),導(dǎo)致性能下降,優(yōu)化快速排序通過(guò)將數(shù)組劃分為三個(gè)區(qū)域,可以更有效地處理重復(fù)元素。 ??本文作者:

    2024年02月11日
    瀏覽(83)
  • [數(shù)據(jù)結(jié)構(gòu) -- 手撕排序算法第六篇] 遞歸實(shí)現(xiàn)快速排序(集霍爾版本,挖坑法,前后指針?lè)橐黄膶?shí)現(xiàn)方法,很能打)

    [數(shù)據(jù)結(jié)構(gòu) -- 手撕排序算法第六篇] 遞歸實(shí)現(xiàn)快速排序(集霍爾版本,挖坑法,前后指針?lè)橐黄膶?shí)現(xiàn)方法,很能打)

    目錄 1、常見(jiàn)的排序算法 1.1 交換排序基本思想 2、快速排序的實(shí)現(xiàn)方法 2.1 基本思想 3 hoare(霍爾)版本 3.1 實(shí)現(xiàn)思路 3.2 思路圖解 3.3 為什么實(shí)現(xiàn)思路的步驟2、3不能交換 3.4 hoare版本代碼實(shí)現(xiàn) 3.5 hoare版本代碼測(cè)試 4、挖坑法 4.1 實(shí)現(xiàn)思路 4.2 思路圖解 4.3 挖坑法代碼實(shí)現(xiàn) 4.4 挖坑

    2024年02月16日
    瀏覽(33)
  • 【數(shù)據(jù)結(jié)構(gòu)】手撕排序

    【數(shù)據(jù)結(jié)構(gòu)】手撕排序

    ?? 博客主頁(yè) : 小羊失眠啦. ?? 系列專欄 : 《C語(yǔ)言》 《數(shù)據(jù)結(jié)構(gòu)》 《Linux》 《Cpolar》 ?? 感謝大家點(diǎn)贊??收藏?評(píng)論?? 排序 :所謂排序就是使一串記錄,按照其中的某個(gè)或某些的大小, 遞增或遞減 的排列起來(lái)的操作。排序算法,就是如何使得記錄按照要求

    2024年02月05日
    瀏覽(34)
  • 【數(shù)據(jù)結(jié)構(gòu)】手撕排序NO.1----排序初識(shí)

    【數(shù)據(jù)結(jié)構(gòu)】手撕排序NO.1----排序初識(shí)

    目錄 ?一. 前言 二. 排序的概念及運(yùn)用 ? ? ? ? 2.1 排序的概念 ? ? ? ? 2.2 排序的運(yùn)用 ? ? ? ? 2.3 常見(jiàn)的排序算法 三.?冒泡and選擇排序 ? ? ? ? 3.1 冒泡排序 ????????3.2 選擇排序 四. 各大排序算法的復(fù)雜度和穩(wěn)定性 ? ? ? ?從本期開(kāi)始,我們的數(shù)據(jù)結(jié)構(gòu)將迎來(lái)一個(gè)新的

    2024年02月16日
    瀏覽(23)
  • [數(shù)據(jù)結(jié)構(gòu) -- 手撕排序第三篇] 冒泡排序

    [數(shù)據(jù)結(jié)構(gòu) -- 手撕排序第三篇] 冒泡排序

    目錄 1、常見(jiàn)的排序算法 1.1 交換排序基本思想 2、冒泡排序的實(shí)現(xiàn) 2.1 基本思想 2.2 單趟排序 2.2.1 單趟排序分析 2.2.2 單趟排序?qū)崿F(xiàn)代碼 3、冒泡排序完整代碼實(shí)現(xiàn) 3.1 思路分析 3.2 代碼實(shí)現(xiàn) 4、時(shí)間復(fù)雜度 5、優(yōu)化算法 5.1 優(yōu)化算法思路 5.2 優(yōu)化算法代碼實(shí)現(xiàn) 6、冒泡排序的特性總

    2024年02月13日
    瀏覽(20)
  • [數(shù)據(jù)結(jié)構(gòu) -- 手撕排序第一篇] 插入排序

    [數(shù)據(jù)結(jié)構(gòu) -- 手撕排序第一篇] 插入排序

    目錄 1、常見(jiàn)的排序算法 2、插入排序的思路 2.1 基本思想 2.2 直接插入排序 2.2.1 單趟排序的思路 2.2.2 單趟排序代碼實(shí)現(xiàn) 3、插入排序代碼 4、插入排序+打印測(cè)試 5、插入排序的時(shí)間復(fù)雜度 5.1 最壞情況 5.2 最好情況 6、直接插入排序的特性總結(jié) ? 直接插入排序是一種簡(jiǎn)單的插入

    2024年02月12日
    瀏覽(18)
  • 【數(shù)據(jù)結(jié)構(gòu)】手撕歸并排序(含非遞歸)

    【數(shù)據(jù)結(jié)構(gòu)】手撕歸并排序(含非遞歸)

    目錄 一,歸并排序(遞歸) 1,基本思想 ?2,思路實(shí)現(xiàn) 二,歸并排序(非遞歸) 1,思路實(shí)現(xiàn) 2,歸并排序的特性總結(jié): 1,基本思想 歸并排序 (MERGE-SORT) 是建立在 歸并操作 上的一種 有效的排序算法 ,該算法是采用 分治法(Divide and Conquer) 的一個(gè)非常典型的應(yīng)用; 將 已

    2024年02月08日
    瀏覽(24)
  • 【數(shù)據(jù)結(jié)構(gòu)】手撕排序NO.2----直接插入排序與希爾排序

    【數(shù)據(jù)結(jié)構(gòu)】手撕排序NO.2----直接插入排序與希爾排序

    ? 目錄 一. 導(dǎo)入 二. 直接插入排序 ? ? ? ? 2.1 基本思想 ? ? ? ? 2.2 過(guò)程分析 ????????2.3 代碼實(shí)現(xiàn) ? ? ? ? 2.4 復(fù)雜度/穩(wěn)定性分析 三. 希爾排序(縮小增量排序) ? ? ? ? 3.1 基本思想 ? ? ? ? 3.2 過(guò)程分析? ????????3.3 代碼實(shí)現(xiàn)? ????????3.4 復(fù)雜度/穩(wěn)定性分析 ?

    2024年02月14日
    瀏覽(21)
  • 數(shù)據(jù)結(jié)構(gòu):手撕圖解七大排序(含動(dòng)圖演示)

    數(shù)據(jù)結(jié)構(gòu):手撕圖解七大排序(含動(dòng)圖演示)

    插入排序分為直接插入排序和希爾排序,其中希爾排序是很值得學(xué)習(xí)的算法 希爾排序的基礎(chǔ)是直接插入排序,先學(xué)習(xí)直接插入排序 直接插入排序類似于打撲克牌前的整牌的過(guò)程,假設(shè)我們現(xiàn)在有2 4 5 3四張牌,那么應(yīng)該怎么整牌? 方法很簡(jiǎn)單,把3插到2和4中間,這樣就完成了

    2024年02月15日
    瀏覽(30)
  • [數(shù)據(jù)結(jié)構(gòu) -- 手撕排序第二篇] 一篇帶你詳細(xì)了解希爾排序

    [數(shù)據(jù)結(jié)構(gòu) -- 手撕排序第二篇] 一篇帶你詳細(xì)了解希爾排序

    目錄 1、常見(jiàn)排序算法 1.1 插入排序基本思想 2、希爾排序 2.1 希爾排序( 縮小增量排序 ) 2.1.1 預(yù)排序階段 2.1.2 插入排序階段 2.2 單趟希爾排序 2.2.1 思路分析 2.2.2 代碼實(shí)現(xiàn) 3、希爾排序代碼實(shí)現(xiàn) 4、希爾排序時(shí)間復(fù)雜度 5、希爾排序與插入排序效率對(duì)比 6、希爾排序特性總結(jié) 直接

    2024年02月13日
    瀏覽(29)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包