您的位置:首页 > 编程语言 > C语言/C++

实现一个简单的c++ list容器(含sort排序 链表归并算法实现)

2012-11-18 21:17 1166 查看
这个其实是很久之前写的,最近参加面试,复习C++,感觉不错,顺便翻出来整理了一遍。

使用过容器的都清楚,容器说白了其实就是一个类模板,它可以存放各种类型。而要对容器元素访问就要通过一个叫

迭代器的东西,迭代器在使用上和指针很相似。因此list容器的实现也主要是对类模板和迭代器的设计,当然也少不了

链表操作,因为list容器是通过链表来存放数据。

一、节点类

该类主要是存放容器内元素的数据(data)

/*
*节点类
*/
template<typename elemType>
class Node
{
private:
elemType data;
Node *next;
public:
Node():next(NULL)
{}
Node(elemType data):data(data),next(NULL)
{}
//类Iter、Mylist要设为友元
friend class Iter<elemType>;
friend class Mylist<elemType>;

};


二、迭代器类

迭代器的实现。看了下面的实现你或许就明白为什么说迭代器和指针很相似,因为它重载了指针的一些基本操作如 ‘*’,'->'等。

记录一个我当时一个很低级的错误:

在实现'->'重载时,我本来是通过间接访问节点数据:

elemType * operator ->()const
{//重载迭代器->操作
return &(node.getData());
}


但这显然是不行的,因为getData()返回的是一个临时变量,对其取到的地址,并非原节点数据的地址。因此要把迭代器类设为节点类的友元类,直接访问节点数据。

如下:

elemType * operator ->()const
{//重载迭代器->操作
return &(node->data);
}


/*
*迭代器类
*/
template<typename elemType>
class Iter
{
private:
Node<elemType> *node;
public:
Iter(){}
Iter(Node<elemType>* a):node(a){}

elemType  operator *() const
{//*重载
return (node->data);
}
elemType * operator ->()const
{//重载迭代器->操作
return &(node->data);
}
bool operator !=(Iter<elemType> &a)const
{//重载迭代器!=操作
return node != a.node;
}
bool operator == (Iter<elemType> &a)const
{//重载迭代器==操作
return node == a.node;
}
Iter<elemType>  operator++(int)
{//重载迭代器++作
Iter<elemType>tmp = *this;
this->node = this->node->next;
return tmp;
}
Node<elemType> * getNode(){ return node;}
};


三、容器类

在这里实现一些基本的容器操作,如push_front()、push_back()、erase()、sort()等。重点讲一下sort()的实现也是花了我最多时间的地方。

本来想用冒泡直接来的,后来发现c++中list容器的sort()函数是通过归并算法实现的,因此我也采用归并DIY一个。

冒泡O(N^2),相比于归并最坏情形运行时间:O(NlogN),当问题规模变大时,冒泡显然是吃不消的。

首先是递归二分链表,递归到最后会把链表分为一个个长度为1的单独节点,然后再有序地往上归并这些节点,把长度为1的扩到2,2扩到4,4扩到8……(这

也是分治思想的精髓)。为了提高二分的效率,二分链表时使用了两个步长一快一慢的指针,快指针的遍历的速度是慢指针的两倍,这样当快指针遍历

到末结点时,慢指针刚好指在了链表的中间结点处。

为了对sort()函数的封装,就要使用函数指针了。容器内定义一个函数指针,测试程序写好cmp()排序方式函数,通过sort(cmp)调用,初始化容器内的

函数指针,使其指向cmp函数。(如果你没使用过STL中的sort()函数,可能你会不明白我在说什么。。)

/*
*容器类
*/
template<typename elemType>
class Mylist
{
private:
int _size;//容器长度
Node<elemType> *head;//指向头结点(不放数据)
Node<elemType> *_end;//指向容器的最后一个元素
bool (*cmp)(elemType a,elemType b);//指针函数,指向给定排序方式的函数

public:
Mylist()
{
head = new Node<elemType>();
head->next = NULL;
_end = head;
this->_size = 0;
}
~Mylist()
{
Node<elemType> *p,*tem;
p = head;
while( p != NULL)
{
tem = p;
p = p->next;
delete tem;
}
}
typedef Iter<elemType> iterator;//定义迭代器类型
void push_back(elemType data)
{//在容器的尾部添加元素
_end->next = new Node<elemType>(data);
_end = _end->next;
_size++;
}
void push_front(elemType data)
{//在容器的前端添加元素
Node<elemType> *p = new Node<elemType>(data);
p->next = head->next;
head->next = p;
if(head == _end)
_end = p;
_size++;
}
int size()
{//返回容器中的元素个数
return _size;
}
iterator begin()
{//返回一个迭代器,它指向容器的第一个元素
iterator iter(head->next);
return iter;
}
iterator end()
{//返返回一个迭代器,它指向容器的最后一个元素的下一位置
iterator iter(_end->next);
return iter;
}
bool erase(iterator iter)
{//删除迭代器 iter 所指向的元素
Node<elemType> *p1 = iter.getNode();
Node<elemType> *p2 = head;
while(p2->next != NULL)
{
if(p2->next == p1)
{
p2->next = p1->next;
if(_end == p1)
_end = p2;
delete p1;
p1 = NULL;
return true;
}
p2 = p2->next;
}
return false;
}
void clear()
{//清空容器
Node<elemType> *p,*tem;
p = head->next;
while( p != NULL)
{
tem = p;
p = p->next;
delete tem;
}
head->next = NULL;
_end = head;
}
/*******以下采用归并算法实现了容器的排序操作*****/
void sort(bool (*cmp)(elemType ,elemType ));
Node<elemType>* mergeSort(Node<elemType> *temHead);
Node<elemType>* merge(Node<elemType> *first,Node<elemType> *second);
};

/*
*初始化排序函数指针
*/
template<typename elemType>
void Mylist<elemType>::sort(bool (*cmp)(elemType ,elemType ))
{
this->cmp = cmp;
head->next=mergeSort(head->next);
}

/*
*二分链表
*/
template<typename elemType>
Node<elemType>* Mylist<elemType>::mergeSort(Node<elemType> *temHead)
{
Node<elemType> *first;
Node<elemType> *second;
first=temHead;
second=temHead;
if(first==NULL||first->next==NULL)
{  //若只有一个节点直接返回(递归临界)
return first;
}
while(second->next!=NULL && second->next->next!=NULL)
{  //利用一快一慢的指针把链表二分
first=first->next; //慢指针
second=second->next->next;//快指针
}
if(first->next!=NULL)
{
second=first->next;
first->next=NULL;
first=temHead;
}
return  merge( mergeSort(first),mergeSort(second) ); //递归二分各个子链表
}

/*
*归并两路链表
*/
template<typename elemType>
Node<elemType>* Mylist<elemType>::merge(Node<elemType> *first,Node<elemType> *second)
{//注意到这里链表first,second已经是顺序的了
Node<elemType> *resList=new Node<elemType>(); //开辟一个临时头节点
Node<elemType> *current;
current=resList;
while(first!=NULL && second!=NULL)
{//某一条链表空时结束
if((*cmp )(first->data,second->data))
{//根据函数指针来确定排序方式
current->next=first;
current=current->next;
first=first->next;
}
else
{
current->next=second;
current=current->next;
second=second->next;
}
}

//把还剩下不空的链表继续接到临时头结点所在的链表
while(first!=NULL)
{
current->next=first;
current=current->next;
first=first->next;
}
while(second!=NULL)
{
current->next=second;
current=current->next;
second=second->next;
}
current = resList->next;
delete resList;//记得释放头结点
return current;
}


四、测试程序

View Code

#include<iostream>
using namespace std;

template<typename elemType>
class Iter;
template<typename elemType>
class Mylist;

/*
*节点类
*/
template<typename elemType>
class Node
{
private:
elemType data;
Node *next;
public:
Node():next(NULL)
{}
Node(elemType data):data(data),next(NULL)
{}
//类Iter、Mylist要设为友元
friend class Iter<elemType>;
friend class Mylist<elemType>;

};

/*
*迭代器类
*/
template<typename elemType>
class Iter
{
private:
Node<elemType> *node;
public:
Iter(){}
Iter(Node<elemType>* a):node(a){}

elemType  operator *() const
{//*重载
return (node->data);
}
elemType * operator ->()const
{//重载迭代器->操作
return &(node->data);
}
bool operator !=(Iter<elemType> &a)const
{//重载迭代器!=操作
return node != a.node;
}
bool operator == (Iter<elemType> &a)const
{//重载迭代器==操作
return node == a.node;
}
Iter<elemType>  operator++(int)
{//重载迭代器++作
Iter<elemType>tmp = *this;
this->node = this->node->next;
return tmp;
}
Node<elemType> * getNode(){ return node;}
};

/*
*容器类
*/
template<typename elemType>
class Mylist
{
private:
int _size;//容器长度
Node<elemType> *head;//指向头结点(不放数据)
Node<elemType> *_end;//指向容器的最后一个元素
bool (*cmp)(elemType a,elemType b);//指针函数,指向给定排序方式的函数

public:
Mylist()
{
head = new Node<elemType>();
head->next = NULL;
_end = head;
this->_size = 0;
}
~Mylist()
{
Node<elemType> *p,*tem;
p = head;
while( p != NULL)
{
tem = p;
p = p->next;
delete tem;
}
}
typedef Iter<elemType> iterator;//定义迭代器类型
void push_back(elemType data)
{//在容器的尾部添加元素
_end->next = new Node<elemType>(data);
_end = _end->next;
_size++;
}
void push_front(elemType data)
{//在容器的前端添加元素
Node<elemType> *p = new Node<elemType>(data);
p->next = head->next;
head->next = p;
if(head == _end)
_end = p;
_size++;
}
int size()
{//返回容器中的元素个数
return _size;
}
iterator begin()
{//返回一个迭代器,它指向容器的第一个元素
iterator iter(head->next);
return iter;
}
iterator end()
{//返返回一个迭代器,它指向容器的最后一个元素的下一位置
iterator iter(_end->next);
return iter;
}
bool erase(iterator iter)
{//删除迭代器 iter 所指向的元素
Node<elemType> *p1 = iter.getNode();
Node<elemType> *p2 = head;
while(p2->next != NULL)
{
if(p2->next == p1)
{
p2->next = p1->next;
if(_end == p1)
_end = p2;
delete p1;
p1 = NULL;
return true;
}
p2 = p2->next;
}
return false;
}
void clear()
{//清空容器
Node<elemType> *p,*tem;
p = head->next;
while( p != NULL)
{
tem = p;
p = p->next;
delete tem;
}
head->next = NULL;
_end = head;
}
/*******以下采用归并算法实现了容器的排序操作*****/
void sort(bool (*cmp)(elemType ,elemType ));
Node<elemType>* mergeSort(Node<elemType> *temHead);
Node<elemType>* merge(Node<elemType> *first,Node<elemType> *second);
};

/*
*初始化排序函数指针
*/
template<typename elemType>
void Mylist<elemType>::sort(bool (*cmp)(elemType ,elemType ))
{
this->cmp = cmp;
head->next=mergeSort(head->next);
while(_end->next != NULL)
{//记得更新_end指向
_end = _end->next;
}
}

/*
*二分链表
*/
template<typename elemType>
Node<elemType>* Mylist<elemType>::mergeSort(Node<elemType> *temHead)
{
Node<elemType> *first;
Node<elemType> *second;
first=temHead;
second=temHead;
if(first==NULL||first->next==NULL)
{  //若只有一个节点直接返回(递归临界)
return first;
}
while(second->next!=NULL && second->next->next!=NULL)
{  //利用一快一慢的指针把链表二分
first=first->next; //慢指针
second=second->next->next;//快指针
}
if(first->next!=NULL)
{
second=first->next;
first->next=NULL;
first=temHead;
}
return  merge( mergeSort(first),mergeSort(second) ); //递归二分各个子链表
}

/*
*归并两路链表
*/
template<typename elemType>
Node<elemType>* Mylist<elemType>::merge(Node<elemType> *first,Node<elemType> *second)
{//注意到这里链表first,second已经是顺序的了
Node<elemType> *resList=new Node<elemType>(); //开辟一个临时头节点
Node<elemType> *current;
current=resList;
while(first!=NULL && second!=NULL)
{//某一条链表空时结束
if((*cmp )(first->data,second->data))
{//根据函数指针来确定排序方式
current->next=first;
current=current->next;
first=first->next;
}
else
{
current->next=second;
current=current->next;
second=second->next;
}
}

//把还剩下不空的链表继续接到临时头结点所在的链表
while(first!=NULL)
{
current->next=first;
current=current->next;
first=first->next;
}
while(second!=NULL)
{
current->next=second;
current=current->next;
second=second->next;
}
current = resList->next;
delete resList;//记得释放头结点
return current;
}

bool cmp(int a, int b)
{//从小到大排序
return a <= b;
}
int main(int argc, char** argv)
{
Mylist<int> test;
Mylist<int>::iterator iter;
for(int i = 0; i < 10; i++)
{
i < 5 ? test.push_back(i): test.push_front(i);
}
cout<<"未排序:";
for(iter = test.begin(); iter != test.end(); iter++)
{
printf("%d ", *iter);
}
cout<<endl;
test.sort(cmp);
cout<<"已排序:";
for(iter = test.begin(); iter != test.end(); iter++)
{
printf("%d ", *iter);
}
cout<<endl;
return 0;
}


运行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐