箱子排序

假定用一个链表保存一个班级学生的清单,节点的数据域有:学生姓名,社会保险号码,
每次作业和考试的分数,所有作业和考试的加权总分,假设分数是0~100的整数,我们按
总分排序。如果采用之前的排序,所需时间都是O(n^2)如果采用箱子排序则快很多。

struct studentRecord
{
    int score;
	string *name;
	int operator!=(const studentRecord& x)const
	{
	    return (score!=x.score);
	}
	int operator int()const{return score;}
}
ostream& operator<<(ostream& out,const studentRecord& x)
{
	out<<x.score<<' '<<*x.name<<endl;
	return out;
}

对!=进行重载使得两个类能够进行直接比较,对int符号进行重载能够使该类能转换成int后
在进行比较。

将箱子排序作为链表chain的成员方法

template<class T>
void chain<T>::binSort(int range)
{
	chainNode<T>**bottom,**top;
	bottom=new chainNode<T>*[range+1];
	top=new chainNode<T>*[range+1];
	for(int b=0;b<=range;b++)
		bottom[b]=NULL;
	for(;firstNode!=NULL;firstNode=firstNode->next)
	{
		int theBin=firstNode->element;//获取当前节点的分数
		if(bottom[theBin]==NULL)//若果与分数编号相同的箱子底部为空,则箱子的头尾指针都指向这个节点
			bottom[theBin]=top[theBin]=firstNode;
		else//若果该箱子的底部不为空,则箱子顶部节点的next指向当前节点,然后更新顶部节点为当前节点
		{
			top[theBin]->next=firstNode;
			top[theBin]=firstNode;
		}
	}
	chainNode<T>*y=NULL;
	for(int theBin=0;theBin<=range;theBin++)
		if(bottom[theBin]!=NULL)//如果箱子不为空
		{
			if(y==NULL)//如果排序的链表为空,则首节点为第一个不空箱子的首节点
				firstNode=bottom[theBin];
			else//如果y不为空,则将前一个箱子的尾节点指向之后不为空的箱子的首节点。
				y->next=bottom[theBin];
			y=top[theBin];//y指向箱子的尾节点
			
		}
		if(y!=NULL)
			y->next=NULL;
		delete [] bottom;
		delete [] top;
}

有一个链表,链表的每个节点都存了一个分数,我们现在要对链表进行排序,我们首先
建立了两个二阶指针数组bottom和top,每个数组的一个元素存取一个节点指针。
然后我们将分数为i且相同的的节点组成一个链表,让bottom指向该链表的头节点,top
指向该链表的尾部节点,最后我们将这些链表的首尾相连就刚好形成了一个有序的链表。

以上箱子排序的缺点大家也应该看出来了,如果我的分数的最大值为10000难道我还要new出
一个容量为10000的数组吗?所以在箱子排序的基础上进行改进推出了基数排序的方法。
基数排序法:
1. 利用箱子排序方法,根据最低位数字(即个位数字),对10个数进行排序,因为每个数都在
0~9 之间,所以range=10;
2. 利用箱子排序方法,根据次低位数字(即十位数字),对10个数进行排序,所以range=10,
因为箱子排序是稳定排序,所以次低位数字相同的节点,按最低位数字排序所得到的次序
保持不变,因此链表是按照最后两位数字进行排序的。
3.~以后的步骤依次类推。

猜你喜欢

转载自blog.csdn.net/du_shuang/article/details/81083613
今日推荐