快速掌握四大排序算法

前言

爲了更加直觀的展示排序的過程,用了動態圖方便理解,並且對每一步的排序過程顯示打印出來。

一 排序算法

1.1什麼是排序

排序是指把一組數據以某種關係(遞增或遞減)按順序排列起來的一種算法。

1.2排序的穩定性

如果在一組需要排序的數據序列中,數據ki和kj的值相同,即ki= =kj,且在排序前ki在序列中的位置領先於kj,那麼當排序後,如果ki和kj的相對前後次序保持不變,即ki仍然領先於kj,則稱此類排序算法是穩定的。如果ki和kj的相對前後次序變了,即kj領先於ki了,則稱此類排序算法是不穩定的。

1.3排序的分類

1.內部排序:指待排序數據全部存放在內存中進行排序的過程。
2.外部排序:指待排序數據的數量很大,內存無法全部容納所有數據,在排序過程中需要對外存進行訪問的排序過程。

1.4排序的過程

排序的過程中需要進行如下兩種基本操作:
(1)比較兩個數據的大小;
(2)移動兩個數據的位置。

1.5排序算法

排序算法按照其實現的思想和方法的不同,可以分爲許多種。
我們比較常用的排序算法有:冒泡排序、 插入排序、選擇排序、希爾排序、快速排序、堆排序、歸併排序。

1.6複雜度

時間複雜度和空間複雜度
在這裏插入圖片描述

二 冒泡排序

2.1動態圖解

在這裏插入圖片描述

2.2基本思路

2.2.1核心思路

n個數據進行冒泡排序,首先將第一個數據和第二個數據進行比較,如果爲逆序就交換兩個數據的值,然後比較第二個和第三個數據,依此類推,直到第最後一個和倒數第二個比較完了爲止。上述過程爲冒泡排序的第一趟冒泡排序,其結果是最大或者最小的數據被放置在末尾的位置。然後進行第二趟排序,把第二大或者第二小的數放置在倒數第二的位置,之後每一趟排序都會使一個數據有序,直到此序列的全部數據都有序爲止。

2.2.2算法實現

void BubSort(int a[],int N)//冒泡排序
{
	for (int i = 0; i < N; i++)//外層是輪數 每一輪選出一個最大的
	{
		for (int j = 0; j <N - i - 1; j++)//內循環是比較
		{
			if (a[j]>a[j + 1])//前後兩個數兩兩進行比較,滿足要求的進行交換
			{
				int temp = a[j];
				a[j] = a[j+1];
				a[j+1] = temp;
			}
		}
}

2.3排序示例

1.代碼實現

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SIZE 10
void BubSort(int a[], int N)//冒泡排序
{
	for (int i = 0; i < N; i++)//外層是輪數 每一輪選出一個最大的
	{
		for (int j = 0; j <N - i - 1; j++)//內循環是比較
		{
			if (a[j]>a[j + 1])//前後兩個數兩兩進行比較,滿足要求的進行交換
			{
				int temp = a[j];//交換
				a[j] = a[j+1];
				a[j+1] = temp;
			}
		}
		printf("第%d步排序結果:", i);
		for (int k = 0; k < N; k++)//把每一步都打印出來
		{
			printf("%d ", a[k]);
		}
		printf("\n");
	}
}
int main()
{
	int shuzu[SIZE], i;
	srand(time(NULL));//生成隨機數種子
	for (i = 0; i < SIZE; i++)//隨機產生SIZE個數據
	{
		shuzu[i] = rand()%100;
	}
	printf("排序前的數組爲:\n");
	for (i = 0; i < SIZE; i++)
	{
		printf("%d ", shuzu[i]);
	}
	printf("\n");
	BubSort(shuzu, SIZE);
	printf("排序後的數組爲:\n");
	for (i = 0; i < SIZE; i++)
	{
		printf("%d ", shuzu[i]);
	}
	printf("\n");
	system("pause");
	return 0;
}

2.結果展示
在這裏插入圖片描述

三 選擇排序

3.1動態圖解

在這裏插入圖片描述

3.2 基本思路

3.2.1核心思路

對一個序列進行選擇排序,首先通過一輪循環比較,從n個數據中找出最大或者最小的那個數據的位置,然後按照遞增或者遞減的順序,將此數據與第一個或最後一個數據進行交換。然後再找第二大或者第二小的數據進行交換,以此類推,直到序列全部有序爲止。

3.2.2算法實現

void SelectionSort(int x[], int n)//選擇排序
{
	int i, j, min,k;
	for (i = 0; i < n; i++)//每一輪選出一個最小的放最左邊
	{
		min=i;//默認當前選擇位置上的元素是最小的
		for (j = i; j < n; j++)//內循環是比較 是不是比它小
		{
			if (x[min] > x[j])
				min = j;//如果有小於默認最小元素min的數組元素,min記錄其下標
		}
		k = x[i];
		x[i] = x[min];
		x[min] = k;
	}
	for (i=0;i<n;i++)
	printf("%d\t",x[i]);
}

3.3排序示例

1.代碼實現

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SIZE 10
void SelectionSort(int a[], int N)
{
	for (int i = 0; i < N; i++)//每一輪選出一個最小的放最左邊
	{
		int min = i;	//默認當前選擇位置上的元素是最小的
		for (int j = i + 1; j < N; j++)//內循環是比較 是不是比它小
		{
			if (a[min]>a[j])
			{
				min = j;	//如果有小於默認最小元素min的數組元素,min記錄其下標
			}
		}
		int k = a[min];
		a[min] = a[i];
		a[i] = k;
		printf("第%d步排序結果:", i);
		for (int h = 0; h < N; h++)
		{
			printf("%d ", a[h]);
		}
		printf("\n");
	}
}
int main()
{
	int shuzu[SIZE];
	srand(time(NULL));
	for (int i = 0; i < SIZE; i++)
	{
		shuzu[i] = rand()%100;
	}
	printf("排序前的數組爲:\n");
	for (int i = 0; i < SIZE; i++)
	{
		printf("%d ", shuzu[i]);
	}
	printf("\n");
	SelectionSort(shuzu, SIZE);
	printf("排序後的數組爲:\n");
	for (int i = 0; i < SIZE; i++)
	{
		printf("%d ", shuzu[i]);
	}
	printf("\n");
	system("pause");
	return  0;
}

2.結果展示
在這裏插入圖片描述

四 插入排序

4.1動態圖解

在這裏插入圖片描述

4.2基本思路

4.2.1核心思路

插入排序的規則是:第一輪開始時默認序列中第一個數據是有序的,之後各個數據以此爲基準,判斷是插入在此數據的前面還是後面,之後的數據依次向後移動,騰出位置,讓數據插入,以此類推,直到整個序列有序爲止。每比較一次,如果滿足條件(升序:前面一個數比後面需要插入的數大),就直接交換。

4.2.2算法實現

void Insort(int x[], int n)//插入排序
{
	for (int i = 1; i < N; i++)//i數據以此爲基準
	{
		for (int j = i; j >= 0; j--)//內循環是比較
		{
			if (x[j]<x[j - 1])	//如果前面有序數列的值比後面的大,就依次交換
			{
				int k = x[j];//交換
				x[j] = x[j - 1];
				x[j - 1] = k;
			}
		}
	}	
}

4.3排序示例

1代碼實現

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SIZE 10
void Insort(int x[], int N) //插入排序
{
	for (int i = 1; i < N; i++)//i數據以此爲基準
	{
		for (int j = i; j >= 0; j--)//內循環是比較
		{
			if (x[j]<x[j - 1])	//如果前面有序數列的值比後面的大,就依次交換
			{
				int k = x[j];//交換
				x[j] = x[j - 1];
				x[j - 1] = k;
			}
		}
		printf("第%d步排序結果:", i);
		for (int h = 0; h < N; h++)
		{
			printf("%3d ", x[h]);
		}
		printf("\n");
	}
}
int main()
{
	int shuzu[SIZE];
	srand(time(NULL));//生成隨機數種子
	for (int i = 0; i < SIZE; i++)//隨機產生SIZE個數據
	{
		shuzu[i] = rand()%100;//隨機數據在100以內
	}
	printf("排序前的數組爲:\n");
	for (int i = 0; i < SIZE; i++)
	{
		printf("%d ", shuzu[i]);
	}
	printf("\n");
	Insort(shuzu, SIZE);
	printf("排序後的數組爲:\n");
	for (int i = 0; i < SIZE; i++)
	{
		printf("%d ", shuzu[i]);
	}
	printf("\n");
	system("pause");
	return  0;
}

2.結果展示
在這裏插入圖片描述

五 快速排序

5.1動態圖解

在這裏插入圖片描述

5.2基本思路

5.2.1核心思路

快速排序的基本思想是:通過一趟排序將待排序的序列劃分爲獨立的兩部分,其中一部分的數據比另一部分的數據小,然後再分別對這兩部分記錄繼續進行排序,直到整個序列有序。
一趟快速排序的具體做法是:設置兩個標記low和high,它們初始值分別指向序列的第一個數據和最後一個數據,並設置一箇中樞變量key,初始值記錄序列第一個數據的值。首先high指針向前搜索,如果找到有數據小於中樞變量key的,則將其數據與中樞變量互相交換;然後low指針向後搜索,如果找到第一個關鍵字大於中樞變量key的,則將其數據與中樞變量互相交換;重複上述步驟,直到low==high爲止。

5.2.2算法實現

void QuickSort(int x[],int low,int high)
{
	int i, j, key;	//變量key是用來保存當前參考元素的值
	if (low<high)	//判斷高低位標記是否重合
	{
		key = x[low];	//key默認保存第一個元素的值
		i = low;	//用i代替最低下標low做運算
		j = high;	//用j代替最高下標high做運算
		while (i < j)	//判斷高低位標記是否重合
		{
			//從數組後半部分向前比較,找到小於參考元素值的位置,直到標記i和j重合
			while (i < j && x[j] >= key)j--;
			if (i < j) x[i++] = x[j];	//數組後半部分的較小元素往前丟
			//從數組前半部分向後比較,找到大於參考元素值的位置,直到標記i和j重合
			while (i < j && x[i] <= key)i++;
			if (i < j) x[j--] = x[i];	//數組前半部分的較大元素往後丟
		}
		x[i] = key;	//參考元素放回數組中
		//把整個數組劃分爲兩半部分,前半部分的元素總是比後半部分小
		QuickSort(x, low, i - 1);	//前半部分遞歸排序
		QuickSort(x, i + 1, high);	//後半部分遞歸排序
	}
}

5.3排序示例

1代碼實現

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SIZE 8
void QuickSort(int x[], int low, int high)//快速排序,後面滿足條件的往前面丟,前面滿足條件的往後面丟
{
	int i, j, key;	//變量key是用來保存當前參考元素的值
	if (low<high)	//判斷高低位標記是否重合
	{
		key = x[low];	//key默認保存第一個元素的值
		i = low;	//用i代替最低下標low做運算
		j = high;	//用j代替最高下標high做運算
		while (i < j)	//判斷高低位標記是否重合
		{
			//從數組後半部分向前比較,找到小於參考元素值的位置,直到標記i和j重合
			while (i < j && x[j] >= key)j--;
			if (i < j) x[i++] = x[j];	//數組後半部分的較小元素往前丟
			//從數組前半部分向後比較,找到大於參考元素值的位置,直到標記i和j重合
			while (i < j && x[i] <= key)i++;
			if (i < j) x[j--] = x[i];	//數組前半部分的較大元素往後丟
		}
		x[i] = key;	//參考元素放回數組中
		//把整個數組劃分爲兩半部分,前半部分的元素總是比後半部分小
		printf("每一步交換結果:");
		for (int h = 0; h < SIZE; h++)
		{
			printf("%3d ", x[h]);
		}
		printf("\n");
		QuickSort(x, low, i - 1);	//前半部分遞歸排序
		QuickSort(x, i + 1, high);	//後半部分遞歸排序
	}
}
int main()
{
	int shuzu[SIZE] , i;
	srand((unsigned int)time(NULL));
	for (i = 0; i < SIZE; i++)
	{
		shuzu[i] = rand()% 100;
	}
	printf("排序前的數組爲:\n");
	for (i = 0; i < SIZE; i++)
	{
		printf("%d ", shuzu[i]);
	}
	printf("\n");
	QuickSort(shuzu, 0, SIZE - 1);
	printf("排序後的數組爲:\n");
	for (i = 0; i < SIZE; i++)
	{
		printf("%d ", shuzu[i]);
	}
	printf("\n");
	system("pause");
	return  0;
}

2.結果展示
在這裏插入圖片描述

六 總結

選擇排序與冒泡排序的區別在於,冒泡排序每比較一次後,滿足條件的數據就交換,而選擇排序是每次比較後,記錄滿足條件數據的位置,一輪循環過後再作交換。
以上都是用到隨機函數,產生一組隨機數據進行排序,並且打印每一步的排序結果。如果對你有幫助的話,請點個贊吧!謝謝你的支持。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章