数据结构学习第十四课(重要八种排序)(下)

本文详细介绍了四种排序算法:箱排序、基数排序、快速排序和归并排序。箱排序通过分箱策略进行排序,基数排序利用数组下标的有序性,快速排序采用分治策略,归并排序则将两个有序数组合并。每种算法都有其适用场景和特点,如快速排序在大多数情况下表现优秀,归并排序则保证了稳定性。
摘要由CSDN通过智能技术生成
5,箱排序
//箱排序
/*
箱排序思想:
按照某种规律,把数据分成若干个箱子装起来,
箱子内部(可以用其他排序方式)
最后把箱子组合在一起;
*/
#include<stdio.h>
#include<string.h>
//数据个数
#define NUM 10
//数据范围
#define AREA 1000
//箱子个数
#define BOX_SIZE 10
void bucket_sort(int* arr, int len);
void bucket_sort(int* arr, int len)
{
	int count;//放箱子次数
	//1,创建箱子
	int* pTemp = new int[BOX_SIZE * len];
	for (count = 1; count < AREA; count *= 10)
	{
		//0,设计好循环
		//当前关注的位 arr[i]/count%10
		//2,初始化箱子
		memset(pTemp, 0, sizeof(int) * (BOX_SIZE * len));
		//3,把数据放到箱子里面
		for (int i = 0; i < len; i++)
		{
			//二维数组写法//ptemp[arr[i] / count % 10][i]=arr[i];
			pTemp[(arr[i] / count % 10) * len + i] = arr[i];
		}
		//4,把数据从箱子里拿出,覆盖原来的数组
		int k = 0;
		for (int i = 0; i < BOX_SIZE * len; i++)
		{
			if (pTemp[i])
			{
				arr[k] = pTemp[i];
				k++;
				//arr[k++]=pTemp[i];
			}
		}
		travel(arr, len);
	}
	//5,释放箱子内存空间
	delete[] pTemp;
}
/*
实际效果:
before: 51 65 48 355 478 666 567 3 47 9
51 3 65 355 666 567 47 48 478 9 //第一次
3 9 47 48 51 355 65 666 567 478
3 9 47 48 51 65 355 478 567 666
after: 3 9 47 48 51 65 355 478 567 666
*/
6,基数排序
/*
基数排序思想:
利用数组下标的天然有序的方式来排序;
限制1:待排数组中不能有重复数据;
限制2:要考虑负数的问题;
限制3:空间浪费地多;
*/
/*
稳定性:
1 不稳定:shell排序 快速排序 插入排序 选择排序
如果数据不同 时间复杂度也不一样
2 稳定:  箱排序 基数排序
如果数据不同 时间复杂度都一样
3 具体使用:
如果排序次数较少:使用稳定的排序
如果排序次数较多:使用不稳定的排序
*/
#include<stdio.h>
#include<string.h>
//数据个数
#define NUM 10
void radix_sort(int* arr, int len,int max);
void radix_sort(int* arr, int len, int max)
{
	//1 申请临时数组内存
	int* pTemp = new int[max + 1];
	//2 初始化临时数组
	memset(pTemp, 0, sizeof(int) * (max + 1));
	//3 把待排数组放到临时数组中去
	for (int i = 0; i < len; i++)
	{
		pTemp[arr[i]] = arr[i];
	}
	//4 从临时数组中把元素覆盖回待排数组
	int k = 0;
	for (int i = 0; i < max + 1; i++)
	{
		if (pTemp[i])
		{
			arr[k++] = pTemp[i];
		}
	}
	//5 释放临时数组内存
	delete[] pTemp;
}
/*
实际效果:
before: 51 65 48 355 478 666 567 3 47 9
after: 3 9 47 48 51 65 355 478 567 666
*/
7,快速排序
/*
快速排序思想:
给整个数组找一个中间值,
保证中间值左边的都比中间值小;
保证中间值右边的都比中间值大;
左边这一组继续分;
右边这一组继续分;
一直分到无法分(数组只有一个元素)为止

步骤:
1 设left下标0 设right下标len-1
2 假设中间值temp为arr[0]
3 循环
arr[right] 和 temp比较 
比temp大 right左移
比temp小 循环结束

arr[left]=arr[right];

arr[left] 和 temp比较
比temp大 循环结束
比temp小 left右移
4 left和right相等
arr[left]=temp;
*/
#include<stdio.h>
#include<string.h>
//数据个数
#define NUM 10
void quick_sort(int* arr, int len);
//具体实现分组
void Quick_sort(int* arr, int right, int left);
void Quick_sort(int* arr, int left, int right)
{
	if (left >= right)return; //一直分到无法分(数组只有一个元素)为止
	//把数组分为两组
	int temp = arr[left];
	int L = left;
	int R = right;
	while (L < R)
	{
		while (L < R && arr[R]>temp)
		{
			R--;
		}
		arr[L] = arr[R];
		while (L < R && arr[L] < temp)
		{
			L++;
		}
		arr[R] = arr[L];
	}
	arr[L] = temp;
	//测试
	printf("左边:(%d -- %d)右边:(%d -- %d)",
		left, L - 1, L + 1, right);
	travel(arr, 10);
	/*
	测试结果:
	左边:(0 -- 3)右边:(5 -- 9)9 47 48 3 51 666 567 478 355 65
左边:(0 -- 0)右边:(2 -- 3)3 9 48 47 51 666 567 478 355 65
左边:(2 -- 2)右边:(4 -- 3)3 9 47 48 51 666 567 478 355 65
左边:(5 -- 8)右边:(10 -- 9)3 9 47 48 51 65 567 478 355 666
左边:(5 -- 4)右边:(6 -- 8)3 9 47 48 51 65 567 478 355 666
左边:(6 -- 7)右边:(9 -- 8)3 9 47 48 51 65 355 478 567 666
左边:(6 -- 5)右边:(7 -- 7)3 9 47 48 51 65 355 478 567 666
	*/
	//组内继续分组
	Quick_sort(arr, left, L-1);//左边这一组
	Quick_sort(arr, L + 1, right);//右边这一组
}
void quick_sort(int* arr, int len)
{
	Quick_sort(arr, 0, len - 1);
	travel(arr,len);
}
/*
实际效果:
before: 51 65 48 355 478 666 567 3 47 9
after: 3 9 47 48 51 65 355 478 567 666
*/
8,归并排序
/*
分治思想:分而治之
	快速排序:一分为二
	归并排序:两个有序数组合并为一个有序数组
*/

/*
	归并排序:两个有序数组合并为一个有序数组
	
	两个指针分别指向两个有序数组
		循环遍历并且比较,符合要求的数据存放到最终的内存段中,并且指针后挪;
		直到有一个数组存放完毕,循环结束;
		将没有放完的数组拷贝到最终的内存段中;
*/
#include<stdio.h>
#include<string.h>

//归并排序
void merge_sort(int* arr, int len);

//递归拆分 left:左边一半第一个元素下标,right:右边一半最后一个元素的下标
void split(int* arr, int left, int right);

//合并 left:左边一半第一个元素下标,mid:左边一半最后一个元素下标,right:右边一半最后一个元素的下标
void combine(int* arr, int left, int mid, int right);
void print(int* arr, int len);
int main()
{
	int arr[10] = { 15,32,89,456,133,20,46,57,77,966 };

	printf("before :");
	print(arr, 10);

	merge_sort(arr, 10);

	printf("after :");
	print(arr, 10);
	return 0;
}

void merge_sort(int* arr, int len)
{
	split(arr, 0, len - 1);
}

void split(int* arr, int left, int right)
{
	if(left < right)//保证拆分到只有一个元素就停止
	{
		//算中间值
		//int mid = (right - left) / 2 + left;
		int mid = (left+right)/2;
		//拆分
		split(arr, left, mid);//拆左边
		split(arr, mid + 1, right);//拆右边
		//合并
		combine(arr, left, mid, right);

		print(arr + left, right - left + 1);
	}
}

void combine(int* arr, int left, int mid, int right)
{
	//申请临时内存段
	int len = right - left + 1;
	int* pTemp = new int[len];
	//循环比较并把数据有序放到pTemp
	int l = left;//左边一半
	int r = mid+1;//右边一半
	int k = 0;//pTemp的下标
	while (l <= mid && r <= right)
	{
		if (arr[l] < arr[r])
		{
			pTemp[k++] = arr[l++];
		}
		else
		{
			pTemp[k++] = arr[r++];
		}
	}
	//把剩下的也放到pTemp
#if 1
	while(l<=mid)pTemp[k++] = arr[l++];
	while(r<=right)pTemp[k++] = arr[r++];
#else
	if (l <= mid)//左边没放完
	{
		memcpy(pTemp + k, arr + l, sizeof(int) * (mid - l + 1));
	}
	else//右边还没有放完
	{
		memcpy(pTemp + k, arr + right, sizeof(int) * (right - r + 1));
	}
	k += (right - r + 1);
#endif
	//pTemp覆盖回arr中
	memcpy(arr + left, pTemp, sizeof(int) * len);

	//释放pTemp
	delete[] pTemp;
}

void print(int* arr, int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值