C++基数排序之队列实现

 一直以来对编程语言方面有特别的喜好,虽然咱是一个小白!这么多年过去了,涉及过不少编程语言,多是浅尝则止,学到皮毛而已。想到非自己的本行,知识水平有限,深入不到哪里去,曾经很长一段时间暂时忘却了它。不料最近又突发兴致,慢慢又捡起以前所学的皮毛,开始学习C++了……呵呵,没办法,喜欢嘛!总感觉自己这辈子走错了行一样……唉,牢骚!就当防止老年痴呆吧!

哈哈~离题万里了 !最近学到有关数据结构的,兴趣挺浓的。边学边试着写代码实现(当然是站在巨人的肩膀之上的!嘻嘻!),以加深自己的理解。还别说,不写则已,一写才发现很多东西都还没搞清楚。也正是因为一写,才发现其中的奥妙!

比如:基数排序吧!之前看了很多其它排序的方法,什么冒泡法呀,交换法呀,选择法呀,插入法呀等等,还有好多高级的排序法。基数排序跟它们比较,感觉完全不一样。其它的都涉及到数据大小的比较,而这个排序完全不管这些,直接机械地但有规律地根据数据的每一位数字,把它排到相应的0-9为脚标的”桶“(我这里是用的队列,其实一个意思吧)里面,再按照0-9的顺序回收到原数组中,完成一次排序。然后根据数据的第二位数字、第三位数字……进行相同的排序、回收,然后结果就这样连大小都没有比(实际上变成了另外一种”比较“:有序存放数据!)结果就出来了!!!效率之高,令小白的我也十分惊叹!!!

理解到这个意思,就动手用队列去实现这种排序法。之前对队列也就是”先进先出“的印象(要不,我是小白呢!大神勿笑哈!),然后其它啥都不了解了,也没有深入进去。一写“队列类”的代码,好像也很简单,一会儿就完成了,没有什么高深的技术难题。突然觉得队列有啥了不起的?直到为了实现基数排序写代码时,才猛然发现:特定情况下,队列真有用!而且队列类的实现代码中,最最关键的,是队列内的数据”自动排队“的实现。这要归功于队列里面两个私有属性front和rear了。而当队列内数据插入或删除影响到front和rear的位置时,最经典的位置计算公式出来了:

front=(front+1)%MAXSIZE

rear=(rear+1)%MAXSIZE

我认为这才是队列这种数据结构最奥妙的地方了!

这些纯属小白的”瞎理解“,大神赞成吗?以后要多动手写代码,要多看多写,才能深入编程的奥妙之中!

下面是我写的代码实现:

#include
#include "Queue.h"
#include


using namespace std;
template
void printArray(T *arr, int size);
//把radixSortCaseMain当作函数用可以(Main()外面用extern声明这个函数),
	//也可以改成Main()函数直接使用。
int radixSortCaseMain() {
	//基数排序,利用队列实现。10个队列,不能多,也不能少。
	const int QUEUE_NUM = 10;
	//参与排序的最大整数数字的位数。由于 rand()产生0-32767之间数字,
		//因此最大位置只有5位了(随机产生数字而言)!
                //要设置更多位数的排序,数据就不能由随机产生,
                //自己手动设置排序的数据吧。
	const int NUMBER_OF_DIGIT = 5;
	//如果排序的数字随机产生,设置它以确保符合最大位数的设置。
	const int  MODULAR_NUM = std::pow(10, NUMBER_OF_DIGIT);
	//参与排序的数字个数。注意不要超过队列能存储的元素个数的最大值。
	const int size = MAXSIZE;
	//存储排序数字的数组。
	int number[size];
	//固定的10个队列
	Queue q[QUEUE_NUM];
	

	
	int i, j, n;

	//设置随机种子,保证每次运行产生的数字都不一样。
	std::srand(time(0));
	for (i = 0;i < size;i++) {
		number[i] = std::rand() % MODULAR_NUM;
		
	}
	//排序前的数字
	printArray(number, size);

	//最大数字有几位数,就排几次。
	for (n = 0;n < NUMBER_OF_DIGIT;n++) {
		//每一次排序思路都是相同的。第一次循环针对个位数字,然后依次十位、百位……

		//第一步:分别根据个位、十位、百位……把对应数字放入对应下标的队列数组里。
			//如:123,个数是3,就把123放进队列下标为3的队列里面。即:q[3]……其它类似!
		for (i = 0;i < size;i++) {
			q[int(number[i] / std::pow(10, n)) % 10].QInsert(number[i]);
		}
	
		//第二步:按队列下标0到9的顺序,依次把每个队列里可能包含的数据全部取出来,
			//依次放进原数组number[]中。只有每个队列取完之后,才进行下一个队列取出数据。
		for (i = 0,j = 0;i < 10;i++) {
			//从队列取数据。由于队列数据弹出即删除,所以取出全部数据后,不必去清空队列。
			while (!q[i].QEmpty()) {
				number[j++] = q[i].QDelete();
			}
			
		}

		
	}

	cout << "排序后的结果:" << endl;
	printArray(number, size);


	return 0;
}

//输出数组数据,有时候经常使用,干脆整个函数吧!
template
void printArray(T *arr, int size) {

	for (int i = 0;i < size;i++) {
		cout << arr[i] << " ";
	}
	cout << endl;
}

 

#pragma once
using namespace std;


//队列内元素最大个数:
static const int MAXSIZE=100;

/*模板队列类
*/

template
class Queue {
private:
	//队首,指向最先出队列的元素位置。
	int front;
	//队尾,指向下一次插入的新元素位置。
	int rear;
	//已经插入队列的元素个数。
	int count;
	//队列内保存元素的数组。
	T qList[MAXSIZE];
public:
	//构造函数
	Queue();
	//插入元素的函数
	bool QInsert(T& item);
	//弹出元素的函数
	T QDelete(void);
	//清空队列
	void QClear(void);
	//返回正在排队的元素个数。
	int QGetCount(void);
	//队列状态函数:是否为空。
	bool QEmpty();
	//队列状态函数:是否已满。
	bool QFull();
	//析构函数
	~Queue();
};

template
Queue::Queue() :front(0),rear(0),count(0){
}

template
bool Queue::QInsert(T& item){
	if (QFull()) {
		cout << "队列已满!插入失败!" << endl;
		return false;
	}
	else {
		count++;
		qList[rear] = item;
		rear = (rear + 1) % MAXSIZE;
		return true;
	}
}



template
T Queue::QDelete(void){
	
	if (QEmpty()) {
		cout << "队列是空的!非正常退出!" << endl;
		exit(1);
	}
	else {
		T temp = qList[front];
		count--;
		front = (front + 1) % MAXSIZE;
		
		return temp;
	}

}
template
void Queue::QClear(void){
	front = rear =count= 0;
}


template
int Queue::QGetCount(void) {
	return count;
}


template
bool Queue::QEmpty(){
	return count == 0;
}
template
bool Queue::QFull(){
	return count == MAXSIZE;
}

template
Queue::~Queue() {

}

 

你可能感兴趣的:(C++)