数据结构 桶排序 基数排序

首先来了解桶排序

将数组分成若干类  分这个类的条件  我们自己决定

这里我们用的是 每隔5个数分为一类

如20~24  25~29 30~34...

数组中的元素满足这样的条件就会被放在相应的桶中

如: 23会被放在20~24的桶中

假设我们有这样一个数组

int arr[15] = { 34,36,31,78,65,32,33,34,89,90,91,67,52,71,77};

我们决定桶的数量 为确保数组中的元素都能如桶   

一般设定为  :

原数组中的最大值-最小值+1 

想判断当前数组元素应该入哪个桶  我们这里的条件是:

当前元素的值-最小值/5   为他要入的桶的下标

如  最小元素20 当前元素40  那么他要进去的桶的下标为 (40-20)/5=4

我们这里所谓的桶  其实就是一个哈希数组 

这里用的是链式存储法 (每一个元素都是一个链表的头)

如相应的桶  就是 把元素添加到哈希数组的相应下标上的链表上去  在这里我们添加用的是

链表插入的方式  直接根据节点的值将节点插入到相应的位置   完成排序 

之后我们只需要 遍历哈希数组并遍历哈希数组元素  吧 哈希数组中的元素都放回到原数组中去

这样就实现了桶排序

桶排序完整代码如下

#include<iostream>
using namespace std;
#define  jiange 5
struct List
{
	int id;
	List* pNext;
};

void Insert(List*&pHead,int value)
{
	List* pTemp=new List;
	pTemp->id = value;
	pTemp->pNext = NULL;
	//链表中没有节点
	if (pHead == NULL)
	{
		pHead = pTemp;
		return;
	}
	//链表中的头节点比当前节点的值大  
	//头插入
	if (pTemp->id < pHead->id)
	{
		pTemp->pNext=pHead;
		pHead = pTemp;
		return;
	}
	//链表的头的值比当前要插入的节点的值小
	//遍历链表  找到要插在谁的后面
	
		List* pMark = pHead;
		while (pMark->pNext != NULL)
		{
			if (pMark->pNext->id > pTemp->id)
			{
				pTemp->pNext = pMark->pNext;
				pMark->pNext = pTemp;
				return;
			}
			pMark = pMark->pNext;
		}
		//遍历到最后一个节点  都没找到比当前节点大的节点  插在最后
		pMark->pNext = pTemp;
		

}
void BuckeSort(int arr[],int nLen)
{
	int begin = arr[0];
	int end =arr[0];
	//参数校验
	if (arr == NULL || nLen <= 10)
	{
		return;
	}
	//找到最大值和最小值确定桶的数量
	for (int i = 0; i < nLen; i++)
	{
		if (arr[i] < begin)
			begin = arr[i];
		if (arr[i] > end)
			end = arr[i];
	}
	int nBucketCount =  end -begin + 1;
	//开辟空间
	List** Hash = new List*[nBucketCount];
	::memset(Hash, 0, sizeof(List*)* nBucketCount);
	//遍历数组入桶
	for (int i = 0; i < nLen; i++)
	{
		//入桶函数
		Insert(Hash[(arr[i]-begin)/jiange], arr[i]);
	}
	//出桶 
	int j = 0;
	for (int i = 0; i < nBucketCount; i++)
	{
		
		while (Hash[i])
		{
			List* pDel = Hash[i];
			Hash[i] = Hash[i]->pNext;

			arr[j++] =pDel->id;
			delete pDel;
			pDel = NULL;
			
			
		}
	}
	delete Hash;
	Hash = NULL;


	

}

int main()
{
	int arr[15] = { 34,36,31,78,65,32,33,34,89,90,91,67,52,71,77};
	BuckeSort(arr, 15);
	for (int val : arr)
	{
		cout << val << " ";
	}
	return 0;
}

基数排序:

可以看做是桶排序的另一种优化  只不过 他的如桶条件变了 

而且需要额外创建一个记录链表的尾的哈希数组;  用于添加节点

尾入  头出

思想:

先把数组中的元素根据个位入桶

出桶放入原数组

在把数组中的元素根据十位入桶

出桶放入原数组...

直到把数组中的元素根据  数组中的最大的元素的最高位  入桶

出桶放入原数组   结束

这样一来  数组自己就排序好了

基数排序:

代码如下

#include<iostream>
using namespace std;
#define  jiange 5
struct List
{
	int id;
	List* pNext;
};

void AddNode(List*& pHead, List*& pEnd ,int value)
{
	List* pTemp = new List;
	pTemp->id = value;
	pTemp->pNext = NULL;
	//链表中没有节点
	if (pHead == NULL)
	{
		pHead = pTemp;
		
	}
	//链表有节点  
	//尾插入
	else 
	{
		pEnd->pNext = pTemp;

	}
		


	
	pEnd = pTemp;
	


}
void RadixSort(int arr[], int nLen)
{
	
	//参数校验
	if (arr == NULL || nLen <= 10)
	{
		return;
	}
	//找到最大值
	int max = arr[0];
	for (int i = 0; i < nLen; i++)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
	}
	int base = 1;
	
	//创建桶中链表的头节点数组
	List** pHeadarr = new List * [10];
	//创建桶中链表的尾节点数组
	List** pEndarr = new List * [10];
	::memset(pHeadarr, 0, sizeof(List*) * 10);
	::memset(pEndarr, 0, sizeof(List*) * 10);
	while (max / base != 0)
	{
		//arr的元素放入桶中
		for (int i = 0; i < nLen; i++)
		{
			
			//链表尾部添加
			AddNode(pHeadarr[arr[i] / base % 10], pEndarr[arr[i] / base % 10], arr[i]);
		}
		//出桶
		int j = 0;
		for (int i = 0; i < 10; i++)
		{
			while (pHeadarr[i])
			{
				List* pDel = pHeadarr[i];
				
				pHeadarr[i] = pHeadarr[i]->pNext;
					
				arr[j++] = pDel->id;
				delete pDel;
				pDel = NULL;
			}
		}
		base *= 10;

	}

	


}

int main()
{
	int arr[15] = { 34,36,31,78,65,32,33,34,89,90,91,67,52,71,77 };
	RadixSort(arr, 15);
	for (int val : arr)
	{
		cout << val << " ";
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值