概述
本次我们讨论一下如何创建并初始化一个链表,然后对其中的元素进行箱子排序。
步骤一
第一步,我们进行前期的代码准备。构建一个结构体作为链表的节点。构建一个类,作为使用链表的接口。
#include<iostream>
using namespace std;
template<class T>
struct chainNode
{
T element;
chainNode<T>* next;
chainNode(){ }
chainNode(const T& element)
{this->element = element;}
chainNode(const T& element,chainNode<T>* next)
{this->element = element;this->next = next;}
};
template<class T>
class chain
{
public:
chain(chainNode<T>* ,int );
chain(int initailCapacity = 10);//
chain(const chain<T>& );//
~chain();//
bool empty(){return listSize = 0;}
int size() const {return listSize;}
T& get(int theIndex) const ;//
int indexOf(T& theElement ) const;
void erase(int theIndex);
void Insert(int theIndex,const T& theElement);
void output(ostream& out) const;
void binSort(int range); //箱子排序
chainNode<T>* getFirstNode();
protected:
void checkIndex(int theIndex) const;
chainNode<T>* firstNode;
int listSize;
};
结构体中包含结构体变量和其不同的构造函数(函数重载),类中包含类的成员变量和类成员函数,提供不同的接口可以完成对链表的不同操作。(其中binSort()函数是我们今天要用的箱子排序函数)
步骤二
我们第二步要去实现箱子排序的算法(很多的数据结构的教材上给出的箱子排序算法在很多的情况下不能直接移植到我们自己写的程序中,需要进行微小但是有很关键的调整,来让代码适合于自己的程序。这里我们首先给出《数据结构、算法与应用》(机械工业出版社)第二版 书中的箱子排序算法。)
下面展示一些 内联代码片
。
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
{
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->next = bottom[theBin];
}
y = top[theBin];
}
if(y != NULL)
{
y->next = NULL;
}
delete [] bottom;
delete [] top;
}
注意观察,这里的排序函数默认的条件是:
首先这个链表的一个单向链表。所以我们在后期写自己的链表的时候也要写单向建表。(后面会介绍如何把这个算法写成一个循环链表,因为单向链表它很浪费迭代器,每次迭代器历遍元素之后很少会重用这个迭代器,我们一般会delete这个迭代器,然后重新建立一个新的迭代器。但是循环链表不同,它可以将一个迭代器多次重复利用。)
步骤三
我们初始化并链表且调用binSort()函数进行排序
下面展示一些 内联代码片
。
int main()
{
chainNode<int> *head,*p;
p = new chainNode<int>;
head = p;
cin>>p->element;
int n;
cin>>n;
for(int i=0;i<n-1;i++)
{
int Element;
cin>>Element;
p->next = new chainNode<int>(Element);
p = p->next;
}
p->next = NULL;
p = p->next;
chainNode<int>* s;
s = head;
chain<int> link(s,n);
link.binSort(51);
chainNode<int>* q ;
q = link.getFirstNode() ;
for(int i = 0; i<n; i++)
{
cout<<q->element<<" ";
q = q->next;
}
cout<<endl;
return 0;
}
这里面要注意的几个问题有:
第一,初始化单向链表的时,定义迭代器p,通过p的移动来进行链表的初始化最后p停在尾节点的前一个位置,因为是单相链表,所以我们给尾节点的next指针赋上NULL。最后将p指针移到尾节点的next指针处(p指针使命完成了。)
第二,重新定义一个s指针指向firstNode,再用s指针初始化link,参与函数binSort的排序就不会出现问题了。
最后,还有一点是,这个排序函数是void型的,所以如果你想要的看函数最后排序的结果的话,我们只能通过排序后的firstNode指针去访问,即函数排序的结果需要一个firstNode的接口去访问。
利用firstNode访问就可以输出最后的排序结果了。
关于循环链表
循环链表和单向链表在这个算法上有细微的差别,下面我们来具体谈一谈
chain类的成员函数binSort函数要多传入一个参数值n 用于记录整个链表的长度。因为在算法中的第一个循环不能再使用 !=NULL这条语句了。所以我们用计数的方法来进行循环次数的控制。其它的没有啥区别,下面展示代码:
template<class T>
void chain<T>::binSort(int range,int n)//箱子排序
{
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(int i = 0;i<n; firstNode = firstNode->next,i++)
{
int theBin = firstNode->element;
if(bottom[theBin] == NULL)
{
bottom[theBin]=top[theBin]=firstNode;
}
else
{
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->next = bottom[theBin];
}
y = top[theBin];
}
if(y != NULL)
{
y->next = NULL;
}
delete [] bottom;
delete [] top;
int main()
{
chainNode<int> *head,*p;
p = new chainNode<int>;
head = p;
cin>>p->element;
int n;
cin>>n;
for(int i=0;i<n-1;i++)
{
int Element;
cin>>Element;
p->next = new chainNode<int>(Element);
p = p->next;
}
p->next = head;
p = p->next;
chain<int> link(p,n);
link.binSort(51,n);
chainNode<int>* q ;
q = link.getFirstNode() ;
for(int i = 0; i<n; i++)
{
cout<<q->element<<" ";
q = q->next;
}
cout<<endl;
return 0;
}
}
以上就是箱子排序的链表表述的全部内容(累死我了)