C语言五大排序(桶排序,冒泡排序,选择排序,插入排序,快速排序)

1、桶排序

概念

桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。

思路

准备桶的时候,桶的大小是原来排序数组中最大元素的值加一,然后遍历无序的数组,把无序数组中的元素的值当成下标给到桶,每存在一个值,桶中的数量就加一。输出的时候,桶的下标值就是之前需要排序的数组的值,只有桶中的数量大于等于一的时候才表示有数据,再进行输出。

无序数组有个要求,就是成员隶属于固定(有限的)的区间,如范围为(0–9)(考试分数为1-100等)

例:
待排数字[6 2 4 1 5 9]

准备10个空桶,最大数个空桶

[6 2 4 1 5 9] 待排数组

[0 0 0 0 0 0 0 0 0 0] 空桶

[0 1 2 3 4 5 6 7 8 9] 桶编号(实际不存在)

1、顺序从待排数组中取出数字,首先6被取出,然后把6入6号桶,这个过程类似这样:空桶[ 待排数组[ 0 ] ] = 待排数组[ 0 ]

[6 2 4 1 5 9] 待排数组

[0 0 0 0 0 0 6 0 0 0] 空桶

[0 1 2 3 4 5 6 7 8 9] 桶编号(实际不存在)

2、顺序从待排数组中取出下一个数字,此时2被取出,将其放入2号桶,是几就放几号桶

[6 2 4 1 5 9] 待排数组

[0 0 2 0 0 0 6 0 0 0] 空桶

[0 1 2 3 4 5 6 7 8 9] 桶编号(实际不存在)

3,4,5,6省略,过程一样,全部入桶后变成下边这样

[6 2 4 1 5 9] 待排数组

[0 1 2 0 4 5 6 0 0 9] 空桶

[0 1 2 3 4 5 6 7 8 9] 桶编号(实际不存在)

0表示空桶,跳过,顺序取出即可:1 2 4 5 6 9

demo

#include <stdio.h>
#include <stdlib.h>

int main()
{
    
    
	
	//桶排序
	//先准备桶  桶的大小是需要排序数组中的最大元素的值加一
	int app[10] = {
    
     0 };

	//无序的数组
	int arr[9]={
    
    5,4,8,6,2,0,3,7,9};
	
	// 遍历无序的数组,把无序数组中的元素的值当成下标给到桶
	for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
	{
    
    
		app[arr[i]]++;     
	}
	输出,把对应的元素出现了几次进行一个输出
	for (int i = 0; i < 10; i++)
	{
    
    
		for (int j = 1; j <= app[i]; j++)
		{
    
    
			printf("%d ", i);
		}
	}	

	printf("\n");

	return 0;
}

运行结果

在这里插入图片描述

2、冒泡排序法

概念

冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。

思路

从左到右,相邻元素进行比较。每次比较一轮,就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右边冒出来。

demo

#include <stdio.h>

//冒泡排序
void bullerSort(int arr[], int len)
{
    
    
	for (int i = 0; i < len - 1; i++)//比较次数
	{
    
    
		for (int j = 0; j < len - 1 - i; j++)//比较过程
		{
    
    
			if (arr[j]>arr[j + 1])//比较
			{
    
    
				//交换
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}
//输出
void print(int arr[], int len)
{
    
    
	for (int i = 0; i < len; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
}
int main()
{
    
    
	int arr[10]={
    
    25,35,68,79,21,13,9,7,16,92};
	bullerSort(arr,10);
	print(arr,10);
	printf("\n");

	return 0;
}

运行结果

在这里插入图片描述

3、选择排序

动态演示

在这里插入图片描述

概念

选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。

思路

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
重复第二步,直到所有元素均排序完毕。

demo

#include <stdio.h>

//选择排序
void selectSort(int arr[], int len)
{
    
    
	for (int i = 0; i < len-1; i++)
	{
    
    
		int min = i;//假设第一个元素是最小的
		for (int j = i + 1; j < len; j++)
		{
    
    
			if (arr[j] < arr[min])
			{
    
    
				min = j;//保存最小元素的下标
			}
		}
		//交换
		int temp = arr[min];
		arr[min] = arr[i];
		arr[i] = temp;
	}
}
//输出
void print(int arr[], int len)
{
    
    
	for (int i = 0; i < len; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
}
int main()
{
    
    
	int arr[15]={
    
    3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};
	selectSort(arr,15);
	print(arr,15);


	printf("\n");
	return 0;
}

运行结果

在这里插入图片描述

4、插入排序

概念

插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

思路

具体算法描述如下:

从第一个元素开始,该元素可以认为已经被排序;
取出下一个元素,在已经排序的元素序列中从后向前扫描;
如果该元素(已排序)大于新元素,将该元素移到下一位置;
重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
将新元素插入到该位置后;
重复步骤2~5。

demo

#include <stdio.h>

//插入排序
void insertSort(int arr[], int len)
{
    
    
	int temp;//保存要插入的元素
	int j;//从当前要要比较插入的元素的前面一个开始
	for (int i = 1; i < len; i++)//第一个元素视为有序,把后面的元素一个一个的插入到前面
	{
    
    
		temp = arr[i];
		j = i - 1;
		while (j >= 0&&arr[j]>temp)
		{
    
    
			arr[j + 1] = arr[j];//前面的元素往后面移动
			j--;
		}
		arr[j + 1] = temp;//把要插入的元素,插入进对应的位置
	}
}
//输出
void print(int arr[], int len)
{
    
    
	for (int i = 0; i < len; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
}
int main()
{
    
    
	int arr[15]={
    
    3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};
	insertSort(arr,15);
	print(arr,15);
	

	printf("\n");
	return 0;
}

运行效果

请添加图片描述

5、快速排序

概念

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

思路

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

从数列中挑出一个元素,称为 “基准”(pivot);
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到 任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

demo

#include <stdio.h>

//快速排序
void quickSort(int arr[], int lift, int right)
{
    
    
	if (lift > right)
		return;
	int i = lift, j = right, temp = arr[i];//获取左右和基准数
	while (i < j)
	{
    
    
		while (temp < arr[j] && i < j)
			j--;
		if (i < j)
			arr[i++] = arr[j];
		while (temp>arr[i] && i < j)
			i++;
		if (i < j)
			arr[j--] = arr[i];
	}
	arr[i] = temp;

	quickSort(arr, lift, i - 1);//左边
	quickSort(arr, i + 1, right);//右边
}
//输出
void print(int arr[], int len)
{
    
    
	for (int i = 0; i < len; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
}
int main()
{
    
    

	int arr[15]={
    
    3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};
	quickSort(arr,0,14);
	print(arr,15);

	printf("\n");
	return 0;
}

运行结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lijunlin0329/article/details/129663221