问题描述:假定用一个链表保存一个班级学生的清单,每个节点的数据域有学生姓名和分数。我们需要对学生们的分数进行排序,其中n为学生总数,箱子排序的思想是首先将分数相同的节点放在同一个箱子里,然后将箱子连接起来就得到有序的链表。
假设分数介于0-5之间,则需要6个箱子,每个箱子对应一个分数。每一个箱子都是一个链表。一个箱子的节点数介于0-n之间,n为总人数。开始时,所有的箱子全部是空的。
解决方案:
- 逐个删除输入链表的节点,将删除的节点分配到对应的箱子里面去
- 将每一个箱子中的链表收集并连接起来,并使之成为一个有序的链表
用于箱子排序的链表元素结构
struct studentRecord
{
int score;
string* name;
int operator != (const studentRecord &x) const
{
return (score != x.score);
}
};
ostream & operator<<(ostream & out, const studentRecord &x)
{
out<<x.score<<' '<<*x.name<<endl;
return out;
}
使用链表的方法进行箱子排序
void binSort(Chain<studentRecord> & theChain, int range)
{
//按分数排序
//对箱子进行初始化
Chain<studentRecord> *bin;
bin = new chain<studentRecord>[range+1]; //每个箱子的容量需要比range多一
//将分数进行装箱操作,从输入链表的首部拿节点,然后删除首节点
int numberOfElements = theChain.size();
for(int i=1;i<=nummberOfElements;i++)
{
studentRecord x = theChain.Get(0); //取首节点数据
theChain.erase(0); //擦除首节点
bin[x.score].insert(0,x); //装箱
}
//从箱子中收集数据
for(int j=range;j>=0;j--)
{
while(!bin[j].empty())
{
studentRecord x = bin[j].get(0); //取数据
bin[j].erase(0); //取完擦出首部节点
theChain.insert(0,x); //插入到theChain链表中
}
}
delete[] bin;
}
附链表Chain节点的结构定义
template<class T>
class chain
{
public:
//构造函数,复制构造函数和析构函数
chain(int initialCapacity =10);
chain(const chain<T> &x);
~chain();
//相关方法
bool empty() const {return listSize ==0 ;}
int size() const{ return listSize;}
T& get(int index) const;
void erase(int index);
void insert(int index, const T& x);
protected:
chainNode<T> *firstNode; //指向链表第一个节点的指针
int listSize; //链表元素个数
};
template<class T>
struct chainNode
{
//数据成员
T element;
chainNode<T> *next;
//方法
chainNode(){}
chainNode(const T& element)
{ this->element = element;}
chainNode(const T& element, chain<T> *next)
{
this->element = element;
this->next = next;
}
};