C++中几种排序算法小结(二)

4、计数排序
与其他排序算法不同的是计数排序算法是利用数组下标来确定元素的位置。
首先,遍历一维数组,从中找出最大值maxNum,接着开辟一块大小为maxNum+1的内存,用于存放计数数组并将计数数组中所有元素置为0。然后,每一个整数按照值对号入座,也就是说第一个整数为5,则5所对应的下标元素加1,以此类推,遍历整个原数组。最终计数数组中的每一个值,就代表了对应整数出现的次数。遍历整数数组,输出元素下标值,其值是几就输出几次。
快速排序取值范围较小的情况下使用效率更高。
参考链接

void CountSort(int Arr[], int size)
{
	int maxNum = Arr[0];
	for (int i = 1; i < size; i++)//找出数组中最大值
	{
		if (Arr[i]>maxNum)
		{
			maxNum = Arr[i];
		}
	}

	int *pTmpArr = new int[maxNum + 1];//创建计数数组,长度为maxNum+1
	memset(pTmpArr, 0x00, sizeof(int)*(maxNum + 1));

	for (int i = 0; i < size; i++)//遍历原数组的元素
	{
		pTmpArr[Arr[i]]++; //对计数数组元素赋值
	}

	int index = 0;//下标
	for (int i = 0; i < maxNum; i++)//从最小的数开始计数,遍历计数数组
	{
		for (int j = 0; j < pTmpArr[i]; j++)//将计数数组的索引值填充到数组中
		{
			Arr[index++] = i;
		}
	}
	delete[]pTmpArr;

}

5、基数排序
个人认为基数排序的思想简单,然而代码实现的过程却比较复杂。
首先,统计数组中的最大位数并定义0~9十个桶。第一次循环先将元素的个位数依次存放于桶中,接着按照从左到右,从上到下依次取出,组成新的数组。第二循环在新的数组中,将十位数数字依次方放在桶中,继续重复上述步骤,直至循环玩最大位数。
参考链接


void RadixSort(int Arr[], int size)//基数排序
{
	int nBits = NumofBitofArr(Arr, size);//求数组中最大的位数
	int nCount[10] = { 0 };//定义10个桶0~9

	int *pTempArr = new int[size];//定义一个临时数组
	memset(pTempArr, 0x00, sizeof(int)*size);//数组中的元素为0

	int radix = 1;
	for (int i = 0; i <= nBits; i++)//统计循环的次数。。也就是说百位就循环2次,千位就循环3次
	{
		memset(nCount, 0x00, sizeof(nCount));//清空桶
		for (int j = 0; j < size; j++)
		{
			nCount[Arr[j] / radix % 10]++;//取个位、十位.....对应的数字取出来
		}

		// 比如经过计算 0, 2, 3, 3, 0, 0, 0, 0, 经过计算 0,2, 5, 8, 0, 0, 。。。
		//2表示比较位为1的元素可以存放在索引为1, 0的位置
	    //5表示比较位为2的元素可以存放在4,3,2  3个位置上(5- 2)
		//8表示比较位为3的元素可以存在7,6,5 3个位置上(8 - 5)
		for (int i = 1; i < 10; i++)
		{
			nCount[i] = nCount[i] + nCount[i + 1];
		}

		for (int j = size-1; j >= 0; j--)//在桶中从个位开始,从下到上依次取出
		{
			int k = Arr[j] / radix % 10;
			pTempArr[nCount[k] - 1] = Arr[j];
			nCount[k]--;
		}

		for (int j = 0; j < size; j++)//重新放在桶中
		{
			Arr[j] = pTempArr[j];
		}

		Display(Arr, size);

		radix *= 10;
	}
}
int NumofBitofArr(int iArr[], int size)//求最大的位数
{
	int nBits = 1;
	int temp = 10;
	for (int i = 0; i < size; i++)
	{
		while (iArr[i] >= temp)
		{
			temp *= 10;
			nBits++;
		}
	}
	return nBits;
}

6、快速排序
首先设定一个基准值,一般以数组中第一数为基准。然后,设定大于基准值的放在右边,小于放在左边。接着,从数组右边最后一个元素开始扫描,遇到比基准值小的就停止,进行数字交换。变换方向,从左边开始扫描,遇到比基准值大停止,进行数字交换。此时分为2个区域,重复上述步骤。
参考链接

void QuickSort(int Arr[], int left, int right)
{
	if (left>=right)
		return;//退出条件

	int Middle = Arr[left];//基准值

	int l = left;//比中间值小的在左边
	int r = right;//比中间值大的在右边

	while (l!=r)
	{
		while (l<r && Arr[r]>=Middle)//首先从数组右边开始扫描,当扫描的值大于等于基准值
			r--;//右边减
		if (l < r)//当小于基准值
			Arr[l] = Arr[r];//就将右边的元素值给左边
		while (l<r && Arr[l]<=Middle) //接着从左边开始扫描,当值小于等于基准值
			l++;//左边加
		if (l<r)
			Arr[r] = Arr[l];//进行数据交换
	}

	Arr[l] = Middle;//将基准值赋予左边

	/*cout << Middle << "为界" << endl;
	Display(Arr, 6);*/

	//采用递归的方式,对于左右2边分别进行快速排序
	QuickSort(Arr, left, l - 1);   //左边
	QuickSort(Arr, l + 1, right);  //右边
}

总体实现

#include "stdafx.h"
#include<iostream>
using namespace std;

void CountSort(int Arr[], int size);//计数排序

void RadixSort(int Arr[], int size);//基数排序

void QuickSort(int Arr[], int left, int right);

void swap(int& num1, int& num2);
void Display(int Arr[], int size);
int NumofBitofArr(int iArr[], int size);//求最大的位数

int _tmain(int argc, _TCHAR* argv[])
{
	int Arr[] = { 23, 46,0, 8, 11, 18 };
	int Arr1[] = { 3, 6,0, 8, 1, 1,8,7,6,5 };
	int size = sizeof(Arr) / sizeof(int);
	Display(Arr, size);
	CountSort(Arr1, size);

    RaxidSort(Arr,size);
	QuickSort(Arr, 0, size-1);

	//Display(Arr, size);
	return 0;
}

void CountSort(int Arr[], int size)
{
	int maxNum = Arr[0];
	for (int i = 1; i < size; i++)//找出数组中最大值
	{
		if (Arr[i]>maxNum)
		{
			maxNum = Arr[i];
		}
	}

	int *pTmpArr = new int[maxNum + 1];//创建计数数组,长度为maxNum+1
	memset(pTmpArr, 0x00, sizeof(int)*(maxNum + 1));

	for (int i = 0; i < size; i++)//遍历原数组的元素
	{
		pTmpArr[Arr[i]]++; //对计数数组元素赋值,统计出现的次数
	}

	int index = 0;//下标
	for (int i = 0; i < maxNum; i++)//从最小的数开始计数,遍历计数数组
	{
		for (int j = 0; j < pTmpArr[i]; j++)//将计数数组的索引值填充到数组中
		{
			Arr[index++] = i;
		}
	}
	delete[]pTmpArr;

}

void RadixSort(int Arr[], int size)//基数排序
{
	int nBits = NumofBitofArr(Arr, size);//求数组中最大的位数
	int nCount[10] = { 0 };//定义10个桶0~9

	int *pTempArr = new int[size];//定义一个临时数组
	memset(pTempArr, 0x00, sizeof(int)*size);//数组中的元素为0

	int radix = 1;
	for (int i = 0; i <= nBits; i++)//统计循环的次数。。也就是说百位就循环2次,千位就循环3次
	{
		memset(nCount, 0x00, sizeof(nCount));//清空桶
		for (int j = 0; j < size; j++)
		{
			nCount[Arr[j] / radix % 10]++;//取个位、十位.....对应的数字取出来
		}

		// 比如经过计算 0, 2, 3, 3, 0, 0, 0, 0, 经过计算 0,2, 5, 8, 0, 0, 。。。
		//2表示比较位为1的元素可以存放在索引为1, 0的位置
	    //5表示比较位为2的元素可以存放在4,3,2  3个位置上(5- 2)
		//8表示比较位为3的元素可以存在7,6,5 3个位置上(8 - 5)
		for (int i = 1; i < 10; i++)
		{
			nCount[i] = nCount[i] + nCount[i - 1];
		}

		for (int j = size-1; j >= 0; j--)//在桶中从个位开始,从下到上依次取出
		{
			int k = Arr[j] / radix % 10;
			pTempArr[nCount[k] - 1] = Arr[j];
			nCount[k]--;
		}

		for (int j = 0; j < size; j++)//重新放在桶中
		{
			Arr[j] = pTempArr[j];
		}

		Display(Arr, size);

		radix *= 10;
	}
}

int NumofBitofArr(int iArr[], int size)//求最大的位数
{
	int nBits = 1;//位数
	int temp = 10;
	for (int i = 0; i < size; i++)//遍历数组中每一个数
	{
		while (iArr[i] >= temp)
		{
			temp *= 10;
			nBits++;
		}
	}
	return nBits;
}

void QuickSort(int Arr[], int left, int right)
{
	if (left>=right)
		return;//退出条件

	int Middle = Arr[left];//基准值

	int l = left;//比中间值小的在左边
	int r = right;//比中间值大的在右边

	while (l!=r)
	{
		while (l<r && Arr[r]>=Middle)//首先从数组右边开始扫描,当扫描的值大于等于基准值
			r--;//右边减
		if (l < r)//当小于基准值
			Arr[l] = Arr[r];//就将右边的元素值给左边
		while (l<r && Arr[l]<=Middle) //接着从左边开始扫描,当值小于等于基准值
			l++;//左边加
		if (l<r)
			Arr[r] = Arr[l];//进行数据交换
	}

	Arr[l] = Middle;//将基准值赋予左边

	/*cout << Middle << "为界" << endl;
	Display(Arr, 6);*/

	//采用递归的方式,对于左右2边分别进行快速排序
	QuickSort(Arr, left, l - 1);   //左边
	QuickSort(Arr, l + 1, right);  //右边
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值