快速掌握四大排序算法

前言

为了更加直观的展示排序的过程,用了动态图方便理解,并且对每一步的排序过程显示打印出来。

一 排序算法

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.结果展示
在这里插入图片描述

六 总结

选择排序与冒泡排序的区别在于,冒泡排序每比较一次后,满足条件的数据就交换,而选择排序是每次比较后,记录满足条件数据的位置,一轮循环过后再作交换。
以上都是用到随机函数,产生一组随机数据进行排序,并且打印每一步的排序结果。如果对你有帮助的话,请点个赞吧!谢谢你的支持。

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