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

【數(shù)據(jù)結(jié)構(gòu)】圖解八大排序(上)

這篇具有很好參考價值的文章主要介紹了【數(shù)據(jù)結(jié)構(gòu)】圖解八大排序(上)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、排序簡介

生活中,我們經(jīng)常能看到排序的應(yīng)用。例如,我們在網(wǎng)購商品的時候,經(jīng)常按銷量從高到低排序。

常見的排序算法有:
【數(shù)據(jù)結(jié)構(gòu)】圖解八大排序(上)
先來介紹一下關(guān)于排序算法的幾個概念。

穩(wěn)定性:相等的元素排序之后相對次序不變
內(nèi)部排序:數(shù)據(jù)全在內(nèi)存中的排序
外部排序:數(shù)據(jù)太多不能同時在內(nèi)存中

下面所有排序算法都以排升序為例。

二、直接插入排序

直接插入排序類似我們平時玩撲克牌的洗牌過程。
【數(shù)據(jù)結(jié)構(gòu)】圖解八大排序(上)
基本思想:把待排序的記錄按其關(guān)鍵碼值的大小逐個插入到一個已經(jīng)排好序的有序序列中,直到所有的記錄插入完為止,得到一個新的有序序列。

如圖所示,我們手上已經(jīng)洗好了 2、4、5、10 四張牌。再拿到一張 7,先跟 10 比,比 10 小,所以再往前比對。跟 5 比,比 5 大,就把 7 挨著插到 5 的后面。這樣我們手上的牌就從四張有序的牌變成五張有序的牌了。

我們來看一個動圖:
【數(shù)據(jù)結(jié)構(gòu)】圖解八大排序(上)
該動圖完整展現(xiàn)了插入排序的過程。

在代碼實現(xiàn)中,我們把牌插到哪個位置,這個位置后面的所有元素就要后挪一位。而后挪會覆蓋我們拿出來的那張牌原本位置的元素,所以應(yīng)該先保存待插元素的值。

完整代碼如下:

void InsertSort(int* a, int n)
{
	for(int i = 1; i < n; i++)
	{
		int tmp = a[i];
		int j = i - 1;
		while(j >= 0 && tmp < a[j])
		{
			a[j + 1] = a[j];
			j--;
		}
		a[j + 1] = tmp;
	}
}
//小區(qū)間優(yōu)化常用插入排序

因此,我們可以發(fā)現(xiàn):

  1. 一開始越接近有序,插入排序的效率就越高。
  2. 插入排序后,相等元素的相對次序是不變的,故插入排序具有穩(wěn)定性。

時間復(fù)雜度:
最壞情況 O(N^2)
最好情況 O(N)

空間復(fù)雜度:O(1)

三、希爾排序

希爾排序,又稱縮小增量排序。

上文提到,對于直接插入排序,一開始越接近有序,排序的效率越高。所以,希爾排序的優(yōu)化方式就是先讓數(shù)組接近有序。

希爾排序包括兩個過程:預(yù)排序直接插入排序。

  1. 預(yù)排序:讓數(shù)組先接近有序。
    按照間隔gap分組,進(jìn)行直接插入排序,可以一組排完再排另一組,也可以多組一起排。
  2. 直接插入排序
    【數(shù)據(jù)結(jié)構(gòu)】圖解八大排序(上)
    在代碼實現(xiàn)中,預(yù)排序其實就是gap > 1時進(jìn)行排序的過程,直接插入排序也就是gap == 1時的排序過程。
    完整代碼如下:
void ShellSort(int* a, int n)
{
	int gap = n / 2;
	while (gap > 0)
	{
		for (int i = gap; i < n; i++)
		{
		    int tmp = a[i];
			int j = i;
			while (j >= gap && tmp < a[j - gap])
			{
				a[j] = a[j - gap];
				j -= gap;
			}
			a[j] = tmp;
		}
		gap /= 2;
	}
}
//對于接近有序的序列,直接插入排序最快
//對于無序的序列,希爾排序能大幅優(yōu)化插入排序的效率

希爾排序的具體效率很難計算,我們暫且認(rèn)為時間復(fù)雜度大約在O(N^1.3)

空間復(fù)雜度:O(1)

另外,在預(yù)排序中,相等元素的相對次序可能會發(fā)生變化,所以希爾排序是不穩(wěn)定的。

四、選擇排序

選擇排序的思想其實非常簡單,以升序為例,就是每次選出最小的換到左邊
【數(shù)據(jù)結(jié)構(gòu)】圖解八大排序(上)
思路非常簡單,來看看代碼怎么寫。

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

時間復(fù)雜度:O(N^2)
空間復(fù)雜度:O(1)

選擇排序是不穩(wěn)定的。

五、堆排序

堆排序是選擇排序的一種,就是把原數(shù)組看成一個堆,利用堆的性質(zhì),對數(shù)組進(jìn)行處理,達(dá)到排序的效果。

需要注意的是:排升序要建大堆,排降序建小堆。

具體過程如下:
【數(shù)據(jù)結(jié)構(gòu)】圖解八大排序(上)
完整代碼如下:

//向下調(diào)整時間復(fù)雜度 O(logN)
void adjustDown(int a[], int parent, int n)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child + 1] > a[child])
		{
			child++;
		}
		if (a[child] > a[parent])
		{
			swap(&a[child], &a[parent]);

			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapSort(int a[], int n)
{
	//建堆時間復(fù)雜度 O(N)
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		adjustDown(a, i, n);
	}

	//排序時間復(fù)雜度 O(NlogN)
	for (int i = n - 1; i >= 0; i--)
	{
		swap(&a[0], &a[i]);

		adjustDown(a, 0, i);
	}
}

時間復(fù)雜度:O(NlogN)
空間復(fù)雜度:O(1)

由于存在堆頂與末尾元素交換的過程,所以堆排序是不穩(wěn)定的。

六、冒泡排序

以排升序為例,從前到后依次比較相鄰兩個元素,如果第一個比第二個大,就兩兩交換。第一趟把最大的元素推到最右邊,第二趟把次大的元素放到倒數(shù)第二個位置,以此類推。

整個過程就像冒泡一樣,每趟都把當(dāng)前區(qū)間最大的元素往右邊推,最后只剩第一個元素的時候本身有序。
【數(shù)據(jù)結(jié)構(gòu)】圖解八大排序(上)

void BubbleSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)//n-1趟
	{
		bool flag = false;//檢查是否交換
		for (int j = 0; j < n - 1 - i; j++)//每趟比較n-1-i次
		{
			if (a[j] > a[j + 1])
			{
				swap(&a[j], &a[j + 1]);
				flag = true;
			}
		}
		if (!flag)//如果沒交換,說明已經(jīng)有序
		{
			break;
		}
	}
}

由于比較相鄰元素時,相等不會交換位置,所以冒泡排序具有穩(wěn)定性。

時間復(fù)雜度:
最壞情況 O(N^2)
最好情況 O(N)

空間復(fù)雜度:O(1)

可以發(fā)現(xiàn),冒泡排序的時間復(fù)雜度無論最壞情況還是最好情況,都和直接插入排序相同。

因此我們可以比較一下二者的效率。

七、冒泡排序與直接插入排序效率對比

數(shù)組有序時:一樣
接近有序時:冒泡慢一些
數(shù)組局部有序:冒泡慢很多

所以,雖然冒泡排序可能是我們最早接觸的一種排序算法,但是它的效率真的很一般,甚至不如直接插入排序。

測試函數(shù):文章來源地址http://www.zghlxwxcb.cn/news/detail-426401.html

void TestOP()
{
	srand(time(0));
	const int N = 50000;
	int* a1 = (int*)malloc(sizeof(int) * N);
	int* a2 = (int*)malloc(sizeof(int) * N);
	int* a3 = (int*)malloc(sizeof(int) * N);
	int* a4 = (int*)malloc(sizeof(int) * N);
	int* a5 = (int*)malloc(sizeof(int) * N);
	int* a6 = (int*)malloc(sizeof(int) * N);
	int* a7 = (int*)malloc(sizeof(int) * N);
	int* a8 = (int*)malloc(sizeof(int) * N);

	for (int i = 0; i < N; ++i)
	{
		a1[i] = rand();
		a2[i] = a1[i];
		a3[i] = a1[i];
		a4[i] = a1[i];
		a5[i] = a1[i];
		a6[i] = a1[i];
		a7[i] = a1[i];
		a8[i] = a1[i];
	}

	int begin1 = clock();
	InsertSort(a1, N);
	int end1 = clock();

	int begin2 = clock();
	ShellSort(a2, N);
	int end2 = clock();

	int begin3 = clock();
	SelectSort(a3, N);
	int end3 = clock();

	int begin4 = clock();
	HeapSort(a4, N);
	int end4 = clock();

	int begin5 = clock();
	BubbleSort(a5, N);
	int end5 = clock();

	int begin6 = clock();
	quicksort(a6, 0, N - 1);
	int end6 = clock();

	int begin7 = clock();
	MergeSort(a7, N);
	int end7 = clock();

	int begin8 = clock();
	CountSort(a8, N);
	int end8 = clock();

	printf("InsertSort:%d\n", end1 - begin1);
	printf("ShellSort:%d\n", end2 - begin2);
	printf("SelectSort:%d\n", end3 - begin3);
	printf("HeapSort:%d\n", end4 - begin4);
	printf("BubbleSort:%d\n", end5 - begin5);
	printf("QuickSort:%d\n", end6 - begin6);
	printf("MergeSort:%d\n", end7 - begin7);
	printf("CountSort:%d\n", end8 - begin8);

	free(a1);
	free(a2);
	free(a3);
	free(a4);
	free(a5);
	free(a6);
	free(a7);
	free(a8);
}

到了這里,關(guān)于【數(shù)據(jù)結(jié)構(gòu)】圖解八大排序(上)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • 【數(shù)據(jù)結(jié)構(gòu)】八大排序(一)

    【數(shù)據(jù)結(jié)構(gòu)】八大排序(一)

    ??作者:日出等日落 ?? 專欄:數(shù)據(jù)結(jié)構(gòu) ? ? ? ? 珍惜自己的時間,利用好每一份每一秒。做事不放過沒一個細(xì)節(jié),小心謹(jǐn)慎,細(xì)致,能夠做到這些,還有什么是不可能的呢? 目錄 ?編輯 ?排序的概念: ?排序的應(yīng)用: ?常見的排序算法: ?常見排序算法的實現(xiàn): ?插入

    2024年02月03日
    瀏覽(40)
  • 【數(shù)據(jù)結(jié)構(gòu)】八大排序算法

    【數(shù)據(jù)結(jié)構(gòu)】八大排序算法

    目錄 一、直接插入排序 二、希爾排序 三、選擇排序 ?3.1、簡單選擇排序 ?3.2、快速選擇排序(Top K問題) 四、堆排序 五、冒泡排序 六、快速排序 ??1、遞歸版本 ? ? ?1.1 hoare 法 ? ? ?1.2 挖坑法 ? ? ?1.3 前后指針法 ? 2、非遞歸版本 ? 3、快速排序的優(yōu)化 ? ? ?3.1 三數(shù)取中

    2024年02月09日
    瀏覽(18)
  • 【數(shù)據(jù)結(jié)構(gòu)】八大排序(一)

    【數(shù)據(jù)結(jié)構(gòu)】八大排序(一)

    目錄 前言: 直接插入排序 直接插入排序代碼實現(xiàn) 直接插入排序特性總結(jié) 希爾排序 希爾排序代碼實現(xiàn) 希爾排序特性總結(jié) 直接選擇排序 直接選擇排序代碼實現(xiàn) 直接選擇排序特性總結(jié) 堆排序 堆的向下調(diào)整算法 建堆 堆排序代碼實現(xiàn) 堆排序特性總結(jié) 排序即使得一串記錄,按照

    2024年02月03日
    瀏覽(16)
  • 【數(shù)據(jù)結(jié)構(gòu)】八大排序(二)

    【數(shù)據(jù)結(jié)構(gòu)】八大排序(二)

    ??作者:日出等日落 ?? 專欄:數(shù)據(jù)結(jié)構(gòu) 在最黑暗的那段人生,是我自己把自己拉出深淵。沒有那個人,我就做那個人。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    2024年02月03日
    瀏覽(20)
  • (數(shù)據(jù)結(jié)構(gòu))八大排序算法

    (數(shù)據(jù)結(jié)構(gòu))八大排序算法

    ?? 排序 (Sorting) 是計算機(jī)程序設(shè)計中的一種重要操作,它的功能是將一個 數(shù)據(jù)元素 (或記錄)的任意序列,重新排列成一個有序的序列。 介紹 :將待排的數(shù),和有序的數(shù)比較,直到一個合適的位置,然后進(jìn)行插入。 示圖 : 將待排數(shù)4,與有序數(shù)對比,然后插入到

    2023年04月21日
    瀏覽(22)
  • 「數(shù)據(jù)結(jié)構(gòu)」八大排序1

    「數(shù)據(jù)結(jié)構(gòu)」八大排序1

    ?? 個人主頁 :Ice_Sugar_7 ?? 所屬專欄 :初階數(shù)據(jù)結(jié)構(gòu) ?? 歡迎點贊收藏加關(guān)注哦! 插排就是將一個元素插入一個有序序列中合適的位置,分為 直接插入排序 和 希爾排序 流程如下: ①保存待插入的值:假設(shè)某一趟中有序序列最后一個元素下標(biāo)為end,先 保存(end+1)位置的

    2024年02月03日
    瀏覽(20)
  • 【數(shù)據(jù)結(jié)構(gòu)】八大排序 (三)

    【數(shù)據(jù)結(jié)構(gòu)】八大排序 (三)

    目錄 前言: 快速排序 快速排序非遞歸實現(xiàn) 快速排序特性總結(jié) 歸并排序 歸并排序的代碼實現(xiàn) 歸并排序的特性總結(jié) 計數(shù)排序 計數(shù)排序的代碼實現(xiàn) 計數(shù)排序的特性總結(jié) 前文快速排序采用了遞歸實現(xiàn),而遞歸會開辟函數(shù)棧幀,遞歸的深度越深,占用棧區(qū)的空間就越大, 棧區(qū)的

    2024年02月01日
    瀏覽(59)
  • 【數(shù)據(jù)結(jié)構(gòu)】八大排序詳解

    【數(shù)據(jù)結(jié)構(gòu)】八大排序詳解

    ?? 作者簡介:一名在后端領(lǐng)域?qū)W習(xí),并渴望能夠?qū)W有所成的追夢人。 ?? 個人主頁:蝸牛牛啊 ?? 系列專欄:??數(shù)據(jù)結(jié)構(gòu)、??C++ ?? 學(xué)習(xí)格言:博觀而約取,厚積而薄發(fā) ?? 歡迎進(jìn)來的小伙伴,如果小伙伴們在學(xué)習(xí)的過程中,發(fā)現(xiàn)有需要糾正的地方,煩請指正,希望能夠與

    2024年02月13日
    瀏覽(21)
  • 數(shù)據(jù)結(jié)構(gòu)--八大排序

    數(shù)據(jù)結(jié)構(gòu)--八大排序

    插入排序的思想跟摸牌很相似,從我們摸到第二張牌的開始,依次將摸到到牌依次有序的插入到手中,最后手牌變成了有序。 有了大致的思路,接下來就要細(xì)分插入排序的細(xì)節(jié)。 首先考慮某一趟的插入排序。為什么先考慮某一趟呢?因為當(dāng)需要解決的問題比較復(fù)雜時先將問

    2024年02月02日
    瀏覽(19)
  • 數(shù)據(jù)結(jié)構(gòu)之八大排序算法

    數(shù)據(jù)結(jié)構(gòu)之八大排序算法

    排序:所謂排序,就是使一串記錄,按照其中的某個或某些的大小,遞增或遞減的排列起來的操作。 下面是常見的排序算法: 直接插入排序是一種簡單的插入排序法,其基本思想是: 把待排序的元素按其值的大小逐個插入到一個已經(jīng)排好序的有序序列中,直到所有的

    2023年04月14日
    瀏覽(23)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包