What:
箱子排序是在链表的基础上进行排序,首先把值相同的节点,放在同一个箱子中,然后把箱子链接起来就得到了有序的链表。
Why:
箱子排序算法的时间复杂度基本保持在Θ(n+2*range),在特殊的场景中有非常好的效果(我不信,因为他排序的数据必须是整型,且如果要对0-999内的10个数进行箱子排序,则至少需要1000个箱子,即range=1000,时间复杂度瞬间升高)。
How:
假设班级里有30个人马上就业毕业了,每个人的本科学生信息表里有一项四学年成绩平均值(中国称为绩点,这里强制它为整数),学校要根据这项数据对这30人进行排名,采用箱子排序。(1)先定义两个数组(bottom[ ]和top[ ]),大小为成绩的最大值,假设全班最高分为100,则数组就有100个。(2)每个箱子都有两个指针,存放在bottom[ ]和top[ ]中,其中bottom[theBin]指向箱子theBin的首节点,top[theBin]指向箱子theBin的尾节点。(3)遍历链表,将数值相同的节点放到一个箱子中,并及时更新bottom和top两个指针,使箱子内形成一个有序链表。(4)链接箱子,根据箱子的标号将所有箱子链接起来。
下面的代码是将箱子排序作为链表的一个成员函数。
struct studentGrade
{
string name;
int grade;
operator int() const{return grade;}
int operator !=(const studentGrade& x)const
{return (grade!=x.grade);}
};
template<class T>
void chainList<T>::binSort(int range)
{
chainList<T> **bottom,**top;
bottom = new chainNode<T> *[range+1];
top = new chainNode<T>* [range+1];
for(int i=0;i<=range;i++)
{
bottom[i]=nullptr;
}
for(;fristNode!=nullptr;fristNode=fristNode->next)
{
int theBin = fristNode->element;
if(bottom[theBin]==nullptr)
{
bottom[theBin]= top[theBin]=fristNode;
}
else
{
top[theBin]->next=fristNode;
top[theBin]=fristNode;
}
}
chainNode<T>* y=nullptr;
for(int i=0;i<=range;i++)
{
if(bottom[i]!=nullptr)
{
if(fristNode==nullptr)
{
fristNode=bottom[i];
}
else
{
y->next=bottom[i];
}
y=top[i];
}
}
if(y!=nullptr)
{
y->next=nullptr;
}
delete []bottom;
delete []top;
}
时间性能分析:
箱子初始化阶段->Θ(range);
箱子分配阶段->Θ(n);
箱子链接阶段->Θ(range);
总的时间性能分析Θ(n+range);