最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言實現(xiàn)單鏈表的快速排序算法

 更新時間:2022年01月20日 09:52:20   作者:CUP-GYC  
大家好,本篇文章主要講的是C語言實現(xiàn)單鏈表的快速排序算法,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下

背景

傳統(tǒng)QuickSort算法最大不足之處在于,由于其基于可索引存儲結(jié)構(gòu)設(shè)計(一般為數(shù)組或索引表),因而無法用于鏈?zhǔn)酱鎯Y(jié)構(gòu),而鏈?zhǔn)酱鎯Y(jié)構(gòu)的實際應(yīng)用非常廣泛,例如動態(tài)存儲管理、動態(tài)優(yōu)先級調(diào)度等等,故本文針對于單向鏈表,以QuickSort的分治策略為基礎(chǔ),提出一種可用于單向鏈表的快速排序算法。

設(shè)計思路

將單向鏈表的首節(jié)點作為樞軸節(jié)點,然后從單向鏈表首部的第二個節(jié)點開始,逐一遍歷所有后續(xù)節(jié)點,并將這些已遍歷節(jié)點的key與樞軸節(jié)點的key進行比較,根據(jù)比較結(jié)果,重新將這些節(jié)點鏈接為less和more兩個單向鏈表,less中所包含節(jié)點的key均小于樞軸節(jié)點的 key;more中所包含節(jié)點的key均大于或等于樞軸節(jié)點的key。然后再對得到的兩個單鏈表進行遞歸操作,將進行內(nèi)部遞歸排序最后連接到樞軸上。同時為達到在每次劃分后將規(guī)模更小的兩個單向鏈表鏈接到樞軸節(jié)點上,必須記錄各自的尾節(jié)點位置,即需要設(shè)置兩個指向尾節(jié)點的指針。less鏈表的首節(jié)點指針設(shè)定為lessHead,尾節(jié)點指針設(shè)定為lessTail;more鏈表的首節(jié)點指針設(shè)定為 moreHead,尾節(jié)點指針設(shè)定為moreTail。當(dāng)前正在遍歷的節(jié)點指針設(shè)定為current。當(dāng)單向鏈表遍歷結(jié)束后,亦即完成了一趟劃分, 如此遞歸進行,便可完成整個單向鏈表的排序。除此之外,為了簡化將 less和more單向鏈表鏈接到樞軸節(jié)點前、后部的過程,還需設(shè)定兩個指向單向鏈表尾節(jié)點的指針 lessTail和moreTail。在遞歸過程中,得到的單鏈表的長度會依次減小,直到長度減小到一的時候即為遞歸出口。

算法主要步驟

步驟1:算法接收兩個指針,其中l(wèi)istHead指 向單向鏈表首節(jié)點,listTail為空指針,劃分過程中,listTail將指向單向鏈表的尾節(jié)點,劃分后用于鏈接less單向鏈表到樞軸節(jié)點前。
步驟2:如果單向鏈表listHead僅有一個節(jié)點,則說明已有序,本層遞歸結(jié)束,返回listHead。
步驟3:令lessHead、lessTail、moreHead和 moreTail為空,令current為listHead的next域,即單向鏈表的第二個節(jié)點。
步驟4:如果current節(jié)點為空,則轉(zhuǎn)入步驟13。
步驟5:如果current節(jié)點的key小于樞軸節(jié)點(即listHead)的key,則current節(jié)點應(yīng)鏈接到 less單向鏈表,轉(zhuǎn)入步驟6;否則,current節(jié)點應(yīng)鏈 接到more單向鏈表,轉(zhuǎn)入步驟9。
步驟6:修改lessTail指針使其指向current 節(jié)點。如果lessHead為空,則轉(zhuǎn)入步驟7;否則轉(zhuǎn)入步驟8。
步驟7:將less節(jié)點鏈接為單鏈表的首節(jié)點。
步驟8:將current節(jié)點鏈接為less單鏈表的尾結(jié)點;
步驟9:修改moreTail指針使其指向current 節(jié)點。如果moreHead為空,則轉(zhuǎn)入步驟10;否則轉(zhuǎn)入步驟11。
步驟10:將currnet節(jié)點鏈接為more單向鏈表的首節(jié)點。
步驟11:將currnet節(jié)點鏈接為more單向鏈表的尾節(jié)點。
步驟12:將current節(jié)點移動到單向鏈表的下一個節(jié)點。
步驟13:如果more單向鏈表不為空,則轉(zhuǎn)入步驟14;否則轉(zhuǎn)入步驟18。
步驟14:標(biāo)記more單向鏈表的結(jié)束位置,即 置moreTail的next域為空。
步驟15:遞歸調(diào)用本算法,繼續(xù)劃分more單 向鏈表,傳人moreHead和moreTail。步驟16將經(jīng)過遞歸排序的more單向鏈表 鏈接到樞軸節(jié)點后。
步驟17:修改listTail指針使其指向more— Tail,以便本層遞歸結(jié)束后供上層遞歸過程使用。
步驟18:由于more單向鏈表為空,則樞軸節(jié) 點便是尾節(jié)點,即置listHead的next域為空。 步驟19:修改listTail指針使其指向listHead。
步驟20:如果less單向鏈表不為空,則轉(zhuǎn)入 步驟21;否則轉(zhuǎn)入步驟24。
步驟21:標(biāo)記less單向鏈表的結(jié)束位置,即 置lessTail的next域為空。
步驟22:遞歸調(diào)用本算法,繼續(xù)劃分less單 向鏈表,傳人lessHead和lessTail。 步驟23將經(jīng)過遞歸排序的less單向鏈表鏈 接到樞軸節(jié)點前。
步驟24:由于less單向鏈表為空,則樞軸節(jié) 點便是首節(jié)點,即置lessHead為listHead。
步驟25:本層遞歸結(jié)束,返回lessHead。
示意圖如下:

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

快速排序算法實現(xiàn)

Linklist Quicksort(Linklist *listHead, Linklist *listTail)
{
	Lnode *current;
	Lnode* lessHead = NULL, *lessTail = NULL, *moreHead = NULL, *moreTail = NULL;
	current = (*listHead)->next;//每次取首節(jié)點為樞紐,current指向第二個節(jié)點用于遍歷
	if ((*listHead)->next != NULL)//當(dāng)鏈表節(jié)點數(shù)不為1時(說明鏈表未排好序)
	{
		for (current = (*listHead)->next; current; current = current->next)
		{
			if (current->key < (*listHead)->key)
			{
				if (lessHead == NULL)
					lessHead = current;
				else
					lessTail->next = current;
				lessTail = current;
			}//current結(jié)點key小于樞紐key時放入less鏈表
			else
			{
				if (moreHead == NULL)
					moreHead = current;
				else
					moreTail->next = current;
				moreTail = current;
			}//current結(jié)點key大于樞紐key時放入more鏈表
		}
		//根據(jù)樞紐結(jié)點將T鏈表分為less和more兩個鏈表
		if (moreTail)
			moreTail->next = NULL;
		if (lessTail)
			lessTail->next = NULL;
		//將more鏈表尾結(jié)點next域置空
		if (moreHead != NULL)
		{
			moreTail->next = NULL;
			Quicksort(&moreHead, &moreTail);
			(*listHead)->next = moreHead;
			*listTail = moreTail;
		}
		//若moreHead不空,則current為more鏈表的尾結(jié)點,對more鏈表進行遞歸處理,將more鏈表接在樞紐節(jié)點后
		else
		{
			(*listHead)->next = NULL;
			*listTail = *listHead;
		}
		//若moreHead為空,則只有l(wèi)ess鏈表(即結(jié)點key全小于樞紐),將樞紐結(jié)點接在less節(jié)點后
		if (lessHead != NULL)
		{
			lessTail->next = NULL;
			Quicksort(&lessHead, &lessTail);
			lessTail->next = *listHead;
			*listHead = lessHead;
		}
		//若lesseHead不空,對less鏈表進行遞歸處理,再將樞紐節(jié)點接在less鏈表后
		else
		{
			lessHead = *listHead;
		}
		//若lesseHead為空,則樞紐結(jié)點作為首節(jié)點
		return lessHead;
	}
	else
		return *listHead;
}

整個程序源代碼

#include<stdio.h>
#include<malloc.h> 
typedef struct Lnode
{
	int key;
	struct Lnode* next;
}Lnode, *Linklist;
//鏈表結(jié)構(gòu)體類型
Linklist createList(Linklist L, int n)
{
	L = (Linklist)malloc(sizeof(Lnode));
	L->next = NULL;
	Lnode *p, *r;
	r = L;
	p = (Lnode*)malloc(sizeof(Lnode));
	scanf("%d", &r->key);
	for (int i = 1; i < n; i++)
	{
		p = (Lnode*)malloc(sizeof(Lnode));
		scanf("%d", &p->key);
		r->next = p;
		r = p;
	}
	r->next = NULL;
	return L;
}
//初始初始化及尾插法(正序)創(chuàng)建單鏈表
Linklist getTail(Linklist L)
{
	while (L->next)
		L = L->next;
	return L;
}
//得到尾指針
void Print(Linklist L)
{
	Lnode *p;
	p = L;
	while (p)
	{
		printf("%d ", p->key);
		p = p->next;
	}
}
//遍歷單鏈表
Linklist Quicksort(Linklist *listHead, Linklist *listTail)
{
	Lnode *current;
	Lnode* lessHead = NULL, *lessTail = NULL, *moreHead = NULL, *moreTail = NULL;
	current = (*listHead)->next;//每次取首節(jié)點為樞紐,current指向第二個節(jié)點用于遍歷
	if ((*listHead)->next != NULL)//當(dāng)鏈表節(jié)點數(shù)不為1時(說明鏈表未排好序)
	{
		for (current = (*listHead)->next; current; current = current->next)
		{
			if (current->key < (*listHead)->key)
			{
				if (lessHead == NULL)
					lessHead = current;
				else
					lessTail->next = current;
				lessTail = current;
			}//current結(jié)點key小于樞紐key時放入less鏈表
			else
			{
				if (moreHead == NULL)
					moreHead = current;
				else
					moreTail->next = current;
				moreTail = current;
			}//current結(jié)點key大于樞紐key時放入more鏈表
		}
		//根據(jù)樞紐結(jié)點將T鏈表分為less和more兩個鏈表
		if (moreTail)
			moreTail->next = NULL;
		if (lessTail)
			lessTail->next = NULL;
		//將more鏈表尾結(jié)點next域置空
		if (moreHead != NULL)
		{
			moreTail->next = NULL;
			Quicksort(&moreHead, &moreTail);
			(*listHead)->next = moreHead;
			*listTail = moreTail;
		}
		//若moreHead不空,則current為more鏈表的尾結(jié)點,對more鏈表進行遞歸處理,將more鏈表接在樞紐節(jié)點后
		else
		{
			(*listHead)->next = NULL;
			*listTail = *listHead;
		}
		//若moreHead為空,則只有l(wèi)ess鏈表(即結(jié)點key全小于樞紐),將樞紐結(jié)點接在less節(jié)點后
		if (lessHead != NULL)
		{
			lessTail->next = NULL;
			Quicksort(&lessHead, &lessTail);
			lessTail->next = *listHead;
			*listHead = lessHead;
		}
		//若lesseHead不空,對less鏈表進行遞歸處理,再將樞紐節(jié)點接在less鏈表后
		else
		{
			lessHead = *listHead;
		}
		//若lesseHead為空,則樞紐結(jié)點作為首節(jié)點
		return lessHead;
	}
	else
		return *listHead;
}
int main()
{
	Lnode* L = NULL;
	int n;
	printf("請輸入元素個數(shù)\n");
	scanf("%d", &n);
	printf("請輸入元素\n");
	L = createList(L, n);
	Lnode* listTail;
	listTail = getTail(L);
	Quicksort(&L, &listTail);
	printf("排序后元素序列為\n");
	Print(L);
	return 0;
}

整個程序已在Visual Studio 2017上運行通過

測試案例

(1)一般數(shù)據(jù)樣例

在這里插入圖片描述

(2)只有一個數(shù)據(jù)時

在這里插入圖片描述

(2)有重復(fù)數(shù)據(jù)時

在這里插入圖片描述

總結(jié)

到此這篇關(guān)于C語言實現(xiàn)單鏈表的快速排序算法的文章就介紹到這了,更多相關(guān)C語言快速排序算法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 從匯編看c++中默認(rèn)構(gòu)造函數(shù)的使用分析

    從匯編看c++中默認(rèn)構(gòu)造函數(shù)的使用分析

    c++中,如果為一個類沒有明確定義一個構(gòu)造函數(shù),那么,編譯器就會自動合成一個默認(rèn)的構(gòu)造函數(shù)。下面,通過匯編程序,來看一下其真實情況
    2013-05-05
  • C++適用于所有輸入法的解決方案

    C++適用于所有輸入法的解決方案

    這篇文章主要介紹了C++適用于所有輸入法的解決方案,文中通過代碼示例講解的非常詳細,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2025-02-02
  • C++實現(xiàn)棧與分析棧的知識點

    C++實現(xiàn)棧與分析棧的知識點

    這篇文章主要介紹了C++實現(xiàn)棧與分析棧的知識點,棧(stack)是計算機中常用的一種線性數(shù)據(jù)結(jié)構(gòu),經(jīng)常有資料使用“操作受限”來形容棧,因為它的壓入棧和彈出棧操作只能在棧頂進行,下文更多相關(guān)資料,需要的小伙伴可以參考一下
    2022-03-03
  • Inline Hook(ring3)的簡單C++實現(xiàn)方法

    Inline Hook(ring3)的簡單C++實現(xiàn)方法

    這篇文章主要介紹了Inline Hook(ring3)的簡單C++實現(xiàn)方法,需要的朋友可以參考下
    2014-08-08
  • C++深入細致探究二叉搜索樹

    C++深入細致探究二叉搜索樹

    二叉搜索樹是以一棵二叉樹來組織的。每個節(jié)點是一個對象,包含的屬性有l(wèi)eft,right,p和key,其中,left指向該節(jié)點的左孩子,right指向該節(jié)點的右孩子,p指向該節(jié)點的父節(jié)點,key是它的值
    2022-05-05
  • C語言 指針與數(shù)組的詳解及區(qū)別

    C語言 指針與數(shù)組的詳解及區(qū)別

    這篇文章主要介紹了C語言 指針與數(shù)組的詳解及對比的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • C/C++細數(shù)宏與函數(shù)有那些區(qū)別

    C/C++細數(shù)宏與函數(shù)有那些區(qū)別

    在C程序中,可以用宏代碼提高執(zhí)行效率。宏代碼本身不是函數(shù),但使用起來象函數(shù)。預(yù)處理器用復(fù)制宏代碼的方式代替函數(shù)調(diào)用,省去了參數(shù)壓棧、生成匯編語言的CALL調(diào)用、返回參數(shù)、執(zhí)行return等過程,從而提高了速度
    2022-10-10
  • C++ OpenCV實現(xiàn)圖像去水印功能

    C++ OpenCV實現(xiàn)圖像去水印功能

    本文將介紹如何使用OpenCV C++ 進行簡單圖像水印去除。我們在網(wǎng)上download圖片時,經(jīng)常因為版權(quán)問題有水印。本案例通過編寫算法進行簡單水印去除。需要的可以參考一下
    2022-01-01
  • C++面試八股文之如何避免死鎖詳解

    C++面試八股文之如何避免死鎖詳解

    在C++中,鎖(Lock)是一種同步工具,用于保護共享資源,防止多個線程同時訪問,那么如何避免死鎖的情況出現(xiàn)呢,下面就為大家簡單講講
    2023-07-07
  • C++ 數(shù)字的反轉(zhuǎn)實現(xiàn)實例

    C++ 數(shù)字的反轉(zhuǎn)實現(xiàn)實例

    這篇文章主要介紹了C++ 數(shù)字的反轉(zhuǎn)實現(xiàn)實例的相關(guān)資料,需要的朋友可以參考下
    2017-06-06

最新評論

重庆市| 鄢陵县| 英德市| 南江县| 深水埗区| 江川县| 泰宁县| 东城区| 临猗县| 永宁县| 石河子市| 府谷县| 仙桃市| 德州市| 邢台市| 西华县| 墨竹工卡县| 黑龙江省| 启东市| 余庆县| 务川| 龙海市| 瓮安县| 山西省| 桃江县| 武清区| 奉新县| 承德县| 宝山区| 郯城县| 临邑县| 郓城县| 浮梁县| 叙永县| 乐山市| 宝兴县| 札达县| 东乡县| 普陀区| 永吉县| 海安县|