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

追夢之旅【數(shù)據(jù)結(jié)構(gòu)篇】——C語言手撕八大經(jīng)典排序

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


追夢之旅【數(shù)據(jù)結(jié)構(gòu)篇】——C語言手撕八大經(jīng)典排序,追夢之旅【數(shù)據(jù)結(jié)構(gòu)篇】,數(shù)據(jù)結(jié)構(gòu),c語言,排序算法

? ?
??博客昵稱:博客小夢
??最喜歡的座右銘:全神貫注的上吧?。?!
??作者簡介:一名熱愛C/C++,算法等技術(shù)、喜愛運(yùn)動、熱愛K歌、敢于追夢的小博主!

??博主小留言:哈嘍!??各位CSDN的uu們,我是你的博客好友小夢,希望我的文章可以給您帶來一定的幫助,話不多說,文章推上!歡迎大家在評論區(qū)嘮嗑指正,覺得好的話別忘了一鍵三連哦!??
追夢之旅【數(shù)據(jù)結(jié)構(gòu)篇】——C語言手撕八大經(jīng)典排序,追夢之旅【數(shù)據(jù)結(jié)構(gòu)篇】,數(shù)據(jù)結(jié)構(gòu),c語言,排序算法

前言??

? ? 哈嘍各位友友們??,我今天又學(xué)到了很多有趣的知識,現(xiàn)在迫不及待的想和大家分享一下!??我僅已此文,手把手帶領(lǐng)大家使用C語言手撕八大經(jīng)典排序~ 都是精華內(nèi)容,可不要錯過喲?。?!??????

排序的認(rèn)識

? 排序分為內(nèi)排序和外排序,這是根據(jù)數(shù)據(jù)在什么位置上進(jìn)行排序而決定的。在內(nèi)存中,對數(shù)據(jù)進(jìn)行排序稱為內(nèi)排序;在外存中,對數(shù)據(jù)進(jìn)行排序稱為外排序。

經(jīng)典的排序有以下幾種:

  • 直接插入排序(InsertSort)
  • 希爾排序(ShellSort)
  • 冒泡排序(BubbleSort)
  • 堆排序(HeapSort)
  • 選擇排序(SelectSort)
  • 快速排序(QuickSort)
  • 歸并排序(MergeSort)
  • 計數(shù)排序(CountSort)

排序的穩(wěn)定性:

其中,歸并排序的身份比較特殊,它既可以做內(nèi)排序,也可以做外排序。其余排序都是屬于內(nèi)排序的。

  1. 穩(wěn)定的排序:直接插入排序,冒泡排序,堆排序,選擇排序,快速排序,
  2. 不穩(wěn)定的排序:希爾排序,歸并排序,計數(shù)排序

排序的時間復(fù)雜度和空間復(fù)雜度以及如何選擇適合的排序:

  • 直接插入排序(InsertSort):時間復(fù)雜度:**O(n2),**空間復(fù)雜度:O(1)。但是,是n2 級別排序中可以說最好的排序。特別是當(dāng)數(shù)據(jù)比較有序或者有序時,最好選擇插入排序。但是如果數(shù)據(jù)一開始是逆序的,那就是最壞的情況。
  • 希爾排序(ShellSort):這個排序的時間復(fù)雜度比較難計算,大約為O(N^1.3)。 時間復(fù)雜度O(1) 。其是在直接排序上的一個改良版解決了數(shù)據(jù)比較隨機(jī)時,插入排序比較慢的缺點(diǎn)。
  • 冒泡排序(BubbleSort):時間復(fù)雜度:O(N^2),空間復(fù)雜度:O(1) 。是比較經(jīng)典的算法,適合小白入門學(xué)習(xí)的第一種算法。本篇文章對此進(jìn)行一個優(yōu)化,當(dāng)數(shù)據(jù)本身就是有序的情況下,可將時間復(fù)雜度優(yōu)化為O(n)。
  • 堆排序(HeapSort): 時間復(fù)雜度:O(N*logn),空間復(fù)雜度:O(1) 。適合大數(shù)據(jù)量的排序,一般可以用來解決TopK的問題。
  • 選擇排序(SelectSort):時間復(fù)雜度:O(N^2),空間復(fù)雜度:O(1) 。是比較差的排序,比冒泡還差。這里是對選擇排序進(jìn)行了優(yōu)化,一般情況下,整體測試性能變得和冒泡差不多了,甚至好一點(diǎn)。
  • 快速排序(QuickSort):時間復(fù)雜度:O(N*logn),空間復(fù)雜度:O(logn) 。幾乎什么情況都是可以使用快速排序。但是還是有一些特殊情況不適合。例如,最左邊的值為最或者最大值,導(dǎo)致一開始選定的keyi為最值。從而惡化為O(n^2)的時間復(fù)雜度,也會有溢出的風(fēng)險。還有就是全為相同數(shù)據(jù)的情況或者其他一些專門針對快排設(shè)計的數(shù)據(jù),都會導(dǎo)致快排變“慢排”。這里進(jìn)行了**三數(shù)取中,小區(qū)間優(yōu)化,三路規(guī)劃,隨機(jī)數(shù)mid ,**解決了目前針對快排的絕大多數(shù)問題。
  • 歸并排序(MergeSort):時間復(fù)雜度:O(N*logn),空間復(fù)雜度:O(n) 。它是完全的二分分割思維,從理論上來,比快排還要快一點(diǎn)。但是由于需要拷貝,拷貝也會消耗性能的,因此其和快排差不多。歸并排序還可以應(yīng)用于外存上的排序場景,這是相對其他排序的一個優(yōu)勢。
  • 計數(shù)排序(CountSort):時間復(fù)雜度:O(N),空間復(fù)雜度:O(max - min + 1 ) 。其性能的好壞取決這一組數(shù)據(jù)中大小的范圍max - min 。在對一組大小比較集中的數(shù)據(jù)進(jìn)行排序時,計數(shù)排序是一個非常好的選擇。

實(shí)現(xiàn)兩個數(shù)交換的代碼

void Swap(int* p1, int* p2)
{
	int tem = *p1;
	*p1 = *p2;
	*p2 = tem;
}

實(shí)現(xiàn)

優(yōu)化版選擇排序

傳統(tǒng)的選擇排序時,一次選定最小的值放到最左邊,以此類推。這里優(yōu)化的思路是:一次選定最小值和最大值,分別放到最左邊和最右邊。

//選擇排序
void SelectSort(int* a, int n)
{
	int left = 0;
	int right = n - 1;
	
	while (left < right)
	{
		int maxi = left;
		int mini = left;
		//找出最大和最小的兩個數(shù)的位置
		for (int i = left; i <= right; i++)
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}
			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}
		
		Swap(&a[mini], &a[left]);
		if (maxi == left)
		{
			maxi = mini;
		}
		Swap(&a[maxi], &a[right]);
		left++;
		right--;
	}
}

冒泡排序

普通版冒泡排序

// 普通版冒泡排序
void BubbleSort(int* a, int len)
{
	for (int i = 0; i < len; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (a[j] > a[j + 1])
			{
				Swap(&a[j], &a[j + 1]);
			}
		}
	}
}

升級版冒泡排序

? 這里是對冒泡排序最好的情況下進(jìn)行一個優(yōu)化,當(dāng)遍歷一遍數(shù)組發(fā)現(xiàn)是有序的,則直接跳出循環(huán)不在交換數(shù)據(jù)。這樣可以將冒泡最好的情況下,優(yōu)化為O(n)。

// 升級版冒泡排序
void BubbleSort(int* a, int len)
{
	for (int i = 0; i < len; i++)
	{
		int flag = 1;
		for (int j = 0; j < len - i - 1; j++)
		{
			if (a[j] > a[j + 1])
			{
				flag = 0;
				Swap(&a[j], &a[j + 1]);
			}
		}
		if (flag == 0)
			break;
	}
}

直接插入排序

? 直接插入排序的實(shí)現(xiàn)思路可以簡單的理解為我們打撲克牌時,進(jìn)行將牌從小到大排序的情況。每次取一個數(shù),和前面的數(shù)比較,并將該數(shù)插入到合適的位置。這樣可以保證,每一次取一個數(shù)據(jù)時,前面的數(shù)都是有效的。

//直接插入排序
void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tem = a[end + 1];
		while (end >= 0)
		{
			if (tem < a[end])
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tem;
	}

}

希爾排序

希爾排序主要是基于插入排序的思想,不同點(diǎn)是希爾排序其利用分組的思想。先進(jìn)行預(yù)排序,將數(shù)據(jù)變得比較有序,再進(jìn)行插入排序的方式。

//希爾排序
void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tem = a[end + gap];
			while (end >= 0)
			{
				if (tem < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tem;
		}
	}
}

堆排序

堆排序是一個比較抽象的排序。邏輯上我們控制的是一個完全二叉樹,物理上我們控制的是一個數(shù)組。這里采用向下調(diào)整算法。

運(yùn)用的知識點(diǎn)和技巧:

  1. 排升序——建大堆
  2. 排降序——建小堆
  3. 左孩子 :child = parent * 2 + 1
  4. 右孩子:child = parent * 2 + 2。
  5. parent = (child - 1) / 2
void AdjustDown(int* a, int n, int  parent)
{
	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 = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}

//堆排序
void HeapSort(int* a, int n)
{
	//建堆--升序建大堆
	//向下調(diào)整建堆 --時間復(fù)雜度:O(n)
	for (int i = (n - 2) / 2; i >= 0; i--)
	{
		AdjustDown(a, n, i);
	}

	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		end--;
	}
}

快速排序

快速排序遞歸版(進(jìn)行過三數(shù)取中優(yōu)化+小區(qū)間優(yōu)化)

三數(shù)取中,解決的是取得keyi是最值的問題。小區(qū)間優(yōu)化,是為了減少遞歸調(diào)用次數(shù)。

快速排序遞歸版1——hoare

注意點(diǎn):

  1. 左邊選keyi,右邊先走;右邊選keyi,左邊先走
  2. 右邊選比 a[keyi]小的值,左邊先比 a[keyi] 大的值
  3. 注意特殊情況對邊界的處理。
// 快速排序hoare版本

int GetMidnum(int* a, int left, int right)
{
	int mid = (left + right) / 2;
	if (a[left] > a[mid])
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if(a[left] > a[right])
		{
			return right;
		}
		else
		{
			return left;
		}
	}
	//a[left] <= a[mid]
	else
	{
		if (a[mid] < a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return right;
		}
		else
		{
			return left;
		}
	}
}

int PartSort1(int* a, int left, int right)
{
	int keyi = left;
	int mid = GetMidnum(a, left, right);
	Swap(&a[mid], &a[keyi]);
	while (left < right)
	{
		while (left < right && a[right] >= a[keyi])
		{
			right--;
		}
		while (left < right && a[left] <= a[keyi])
		{
			left++;
		}
		Swap(&a[left], &a[right]);
	}
	Swap(&a[left], &a[keyi]);
	keyi = left;
	return keyi;

}
快速排序遞歸版2——挖坑法

這個和hoare版本差不多,只是在理解的思維上有所不同。挖坑法的思路是比較好理解的。不同區(qū)哪個先走的問題。

// 快速排序挖坑法
int GetMidnum(int* a, int left, int right)
{
	int mid = (left + right) / 2;
	if (a[left] > a[mid])
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if(a[left] > a[right])
		{
			return right;
		}
		else
		{
			return left;
		}
	}
	//a[left] <= a[mid]
	else
	{
		if (a[mid] < a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return right;
		}
		else
		{
			return left;
		}
	}
}


int PartSort2(int* a, int left, int right)
{
	int mid = GetMidnum(a, left, right);
	Swap(&a[mid], &a[left]);
	int key = a[left];
	int hole = left;
	while (left < right)
	{
		while (left < right && a[right] >= key)
		{
			right--;
		}
		a[hole] = a[right];
		hole = right;
		while (left < right && a[left] <= key)
		{
			left++;
		}
		a[hole] = a[left];
		hole = left;
	}
	a[left] = key;
	return left;

}

快速排序遞歸版3——前后指針法

這個版本是我比較推薦的快速排序的實(shí)現(xiàn)方法。主要是因?yàn)槠渚帉懘a的坑相對于上面兩種比較少。而且整體代碼比較簡短。

// 快速排序前后指針法
int GetMidnum(int* a, int left, int right)
{
	int mid = (left + right) / 2;
	if (a[left] > a[mid])
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if(a[left] > a[right])
		{
			return right;
		}
		else
		{
			return left;
		}
	}
	//a[left] <= a[mid]
	else
	{
		if (a[mid] < a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return right;
		}
		else
		{
			return left;
		}
	}
}


int PartSort3(int* a, int left, int right)
{
	int keyi = left;
	int prev = left;
	int cur = prev + 1;
	int mid = GetMidnum(a, left, right);
	Swap(&a[mid], &a[left]);
	while (cur <= right)
	{
		if (a[cur] < a[keyi] && prev++ != cur)
		{
			Swap(&a[cur], &a[prev]);
		}
		cur++;
	}
	Swap(&a[prev], &a[keyi]);
	keyi = prev;
	return prev;
}

上述三個版本,在性能上沒有什么差別,只是在思維的理解上,挖坑法比較好理解。而前后指針法比較好寫代碼。

快速排序非遞歸1

快速排序的非遞歸實(shí)現(xiàn),需要利用數(shù)據(jù)結(jié)構(gòu)棧。解決的是,遞歸版本下,棧溢出的情況。

// 快速排序 非遞歸實(shí)現(xiàn)
void QuickSortNonR(int* a, int left, int right)
{
	ST st;
	STInit(&st);
	if (left < right)
	{
		STPush(&st, right);
		STPush(&st, left);
	}
	while (!STEmpty(&st))
	{
		int begin = STTop(&st);
		STPop(&st);
		int end = STTop(&st);
		STPop(&st);
		int keyi = PartSort3(a, begin, end);
		//[begin,keyi - 1] keyi [ keyi + 1, end]
		if (keyi + 1 < end)
		{
			STPush(&st, end);
			STPush(&st, keyi + 1);
		}

		if (begin < keyi - 1)
		{
			STPush(&st, keyi - 1);
			STPush(&st, begin);
		}
	}

	STDestroy(&st);
}

快速排序非遞歸2

棧實(shí)現(xiàn)的頭文件.h

#pragma once
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

void STInit(ST* pst);
void STDestroy(ST* pst);
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);

棧實(shí)現(xiàn)的功能文件.c


#include "Stack.h"

void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;

	//pst->top = -1;   // top 指向棧頂數(shù)據(jù)
	pst->top = 0;   // top 指向棧頂數(shù)據(jù)的下一個位置

	pst->capacity = 0;
}

void STDestroy(ST* pst)
{
	assert(pst);

	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

void STPush(ST* pst, STDataType x)
{
	if (pst->top == pst->capacity)
	{
		int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, newCapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}

		pst->a = tmp;
		pst->capacity = newCapacity;
	}

	pst->a[pst->top] = x;
	pst->top++;
}

void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));

	pst->top--;
}

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));

	return pst->a[pst->top - 1];
}

bool STEmpty(ST* pst)
{
	assert(pst);

	/*if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/

	return pst->top == 0;
}

int STSize(ST* pst)
{
	assert(pst);

	return pst->top;
}

歸并排序

歸并排序遞歸版

歸并排序遞歸版1(進(jìn)行過小區(qū)間優(yōu)化)

歸并排序是一個使用二分來劃分區(qū)間,然后進(jìn)行歸并的排序。主要還是要注意區(qū)間的劃分。

void _MergeSort(int* a, int begin, int end, int* tem)
{
    // 遞歸結(jié)束的條件
	if (begin == end)
		return;
    //小區(qū)間優(yōu)化
	if ((begin - end) < 10)
	{
		InsertSort(a, begin - end + 1);
	}
	int mid = (begin + end) / 2;
	//[left , mid] [ mid + 1, right]
	_MergeSort(a, begin, mid, tem);
	_MergeSort(a, mid + 1, end, tem);

	//歸并數(shù)據(jù)
	int begin1 = begin, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	int i = begin;
	while (begin1 <= end1 && begin2 <= end2) 
	{
		if (a[begin1] < a[begin2])
		{
			tem[i++] = a[begin1++];
		}
		else
		{
			tem[i++] = a[begin2++];
		}
	}

	while (begin1 <= end1)
	{
		tem[i++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tem[i++] = a[begin2++];
	}
	memmove(a + begin, tem + begin, sizeof(int) * (end2 - begin + 1));

}

//歸并排序 -- 遞歸版
void MergeSort(int* a, int n)
{
	int* tem = (int*)malloc(sizeof(int) * n);
	_MergeSort(a, 0, n - 1,tem);
	free(tem);
}

歸并排序非遞歸版

歸并排序非遞歸版1(部分歸并思路實(shí)現(xiàn))

非遞歸版本的歸并排序,最主要的是要處理好區(qū)間邊界的問題和修正,防止越界。以及拷貝數(shù)據(jù)時,區(qū)間的邊界把控問題。

//歸并排序 -- 非遞歸版1
void MergeSortNonR(int* a, int n)
{
	int* tem = (int*)malloc(sizeof(int) * n);
	int begin = 0;
	int end = n - 1;
	int gap = 1;

	while (gap < n)
	{
		int j = 0;
		for (int i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			//printf("修正前:[ %d , %d ] [ %d , %d ]\n",begin1,end1,begin2,end2);
			if (end1 >= n || begin2 >= n)
			{
				break;
			}
			if (end2 >= n)
			{
				end2 = n - 1;
			}
			//printf("修正后:[ %d , %d ] [ %d , %d ]\n", begin1, end1, begin2, end2);
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
				{
					tem[j++] = a[begin1++];
				}
				else
				{
					tem[j++] = a[begin2++];
				}
			}

			while (begin1 <= end1)
			{
				tem[j++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tem[j++] = a[begin2++];
			}
			memmove(a + i, tem + i, sizeof(int) * (end2 - i + 1));
			
		}
		gap *= 2;
	}
}

歸并排序非遞歸版2(整體歸并思路實(shí)現(xiàn))
//歸并排序 -- 非遞歸版2
void MergeSortNonR2(int* a, int n)
{
	int* tem = (int*)malloc(sizeof(int) * n);
	int begin = 0;
	int end = n - 1;
	int gap = 1;

	while (gap < n)
	{
		int j = 0;
		for (int i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			//printf("修正前:[ %d , %d ] [ %d , %d ]\n",begin1,end1,begin2,end2);
			if (end1 >= n)
			{
				end1 = n - 1;
				begin2 = n;
				end2 = n - 1;
			}
			else if(begin2 >= n)
			{
				begin2 = n;
				end2 = n - 1;
			}
			else if(end2 >= n)
			{
				end2 = n - 1;
			}
			//printf("修正后:[ %d , %d ] [ %d , %d ]\n", begin1, end1, begin2, end2);
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
				{
					tem[j++] = a[begin1++];
				}
				else
				{
					tem[j++] = a[begin2++];
				}
			}

			while (begin1 <= end1)
			{
				tem[j++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tem[j++] = a[begin2++];
			}
		}
		memmove(a, tem, sizeof(int) * n);
		gap *= 2;
	}
}

? ?對于上述的排序,我都進(jìn)行了一個驗(yàn)證,結(jié)果都是正確的。

追夢之旅【數(shù)據(jù)結(jié)構(gòu)篇】——C語言手撕八大經(jīng)典排序,追夢之旅【數(shù)據(jù)結(jié)構(gòu)篇】,數(shù)據(jù)結(jié)構(gòu),c語言,排序算法

總結(jié)撒花

? ?本篇文章旨在分享的是C語言手撕八大經(jīng)典排序。希望大家通過閱讀此文有所收獲
? ???如果我寫的有什么不好之處,請在文章下方給出你寶貴的意見??。如果覺得我寫的好的話請點(diǎn)個贊贊和關(guān)注哦~??????文章來源地址http://www.zghlxwxcb.cn/news/detail-582780.html

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

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(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)來模擬遞歸,實(shí)現(xiàn)快排的非遞歸版本;遞歸版本測試OJ題時,有大量重復(fù)元素樣例不能通過,導(dǎo)致性能下降,優(yōu)化快速排序通過將數(shù)組劃分為三個區(qū)域,可以更有效地處理重復(fù)元素。 ??本文作者:

    2024年02月11日
    瀏覽(83)
  • 數(shù)據(jù)結(jié)構(gòu)之隊列詳解(C語言手撕)

    數(shù)據(jù)結(jié)構(gòu)之隊列詳解(C語言手撕)

    ??個人名片: ??作者簡介:一名樂于分享在學(xué)習(xí)道路上收獲的大二在校生 ??個人主頁??:GOTXX ??個人WeChat:ILXOXVJE ??本文由GOTXX原創(chuàng),首發(fā)CSDN?????? ??系列專欄:零基礎(chǔ)學(xué)習(xí)C語言----- 數(shù)據(jù)結(jié)構(gòu)的學(xué)習(xí)之路----C++的學(xué)習(xí)之路 ??每日一句:如果沒有特別幸運(yùn),那就請?zhí)?/p>

    2024年03月10日
    瀏覽(30)
  • 數(shù)據(jù)結(jié)構(gòu)之單鏈表詳解(C語言手撕)

    數(shù)據(jù)結(jié)構(gòu)之單鏈表詳解(C語言手撕)

    ? ??文章簡介: 概念:鏈表是一種物理存儲結(jié)構(gòu)上非連續(xù)、非順序的存儲結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的 從圖片中可以看出,鏈表的每個節(jié)點(diǎn)都是一個結(jié)構(gòu)體,該結(jié)構(gòu)體中有一個存儲數(shù)據(jù)的變量和一個指向下一節(jié)點(diǎn)的結(jié)構(gòu)體指針; 在邏輯上

    2024年03月10日
    瀏覽(25)
  • 數(shù)據(jù)結(jié)構(gòu)之棧詳解(C語言手撕)

    數(shù)據(jù)結(jié)構(gòu)之棧詳解(C語言手撕)

    ??個人名片: ??作者簡介:一名樂于分享在學(xué)習(xí)道路上收獲的大二在校生 ??個人主頁??:GOTXX ??個人WeChat:ILXOXVJE ??本文由GOTXX原創(chuàng),首發(fā)CSDN?????? ??系列專欄:零基礎(chǔ)學(xué)習(xí)C語言----- 數(shù)據(jù)結(jié)構(gòu)的學(xué)習(xí)之路----C++的學(xué)習(xí)之路 ??每日一句:如果沒有特別幸運(yùn),那就請?zhí)?/p>

    2024年03月19日
    瀏覽(22)
  • [C語言實(shí)現(xiàn)]數(shù)據(jù)結(jié)構(gòu)——手撕順序棧之我出生就會寫一個棧

    [C語言實(shí)現(xiàn)]數(shù)據(jù)結(jié)構(gòu)——手撕順序棧之我出生就會寫一個棧

    ??作者: FlashRider ??專欄: 數(shù)據(jù)結(jié)構(gòu) 目錄 棧的前置知識 1.什么是棧? 2.生活中哪些地方有棧的影子? 順序表實(shí)現(xiàn)棧 1.為什么通常采用順序表實(shí)現(xiàn)棧? 2.棧的實(shí)現(xiàn) 棧( stack )又名堆棧,它是一種 運(yùn)算受限的線性表 。限定僅在表尾進(jìn)行插入和刪除操作的線性表。這一端被稱為

    2024年02月08日
    瀏覽(23)
  • 數(shù)據(jù)結(jié)構(gòu)__<八大排序> __插入排序 |希爾排序 |選擇排序 |堆排序 |快速排序 |歸并排序(C語言實(shí)現(xiàn))

    數(shù)據(jù)結(jié)構(gòu)__<八大排序> __插入排序 |希爾排序 |選擇排序 |堆排序 |快速排序 |歸并排序(C語言實(shí)現(xiàn))

    目錄 插入排序? 希爾排序 選擇排序 堆排序 冒泡排序 快速排序 hoare法 挖坑法 前后指針法 快排特性總結(jié) 三數(shù)取中優(yōu)化 小區(qū)間優(yōu)化 快排非遞歸 歸并排序 歸并排序非遞歸 計數(shù)排序 總結(jié) OJ測試 1、元素集合越接近有序,直接插入排序算法的時間效率越高 2、時間復(fù)雜度:O(N^2

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

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

    目錄 前言: 直接插入排序 直接插入排序代碼實(shí)現(xiàn) 直接插入排序特性總結(jié) 希爾排序 希爾排序代碼實(shí)現(xiàn) 希爾排序特性總結(jié) 直接選擇排序 直接選擇排序代碼實(shí)現(xiàn) 直接選擇排序特性總結(jié) 堆排序 堆的向下調(diào)整算法 建堆 堆排序代碼實(shí)現(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) ?? 歡迎點(diǎn)贊收藏加關(guān)注哦! 插排就是將一個元素插入一個有序序列中合適的位置,分為 直接插入排序 和 希爾排序 流程如下: ①保存待插入的值:假設(shè)某一趟中有序序列最后一個元素下標(biāo)為end,先 保存(end+1)位置的

    2024年02月03日
    瀏覽(20)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包