/*
* =====================================================================================
*
* Filename: d_list.h
*
* Description: 看了循环链表,写个代码练习练习
* 循环链表
* 优点: 删除操作节点或整个链表的操作可以在常数的时间内完成
*
*
* Version: 1.0
* Created: 08/25/2012 05:55:21 PM
* Revision: none
* Compiler: g++
*
* Author: lsff (lsff),
* Organization:
*
* =====================================================================================
*/
#ifndef CLIST_H
#define CLIST_H
#include <iostream>
using namespace std;
typedef int T;
struct lnode
{
T data;
lnode *next;
lnode(const T& data=T()):data(data),next(NULL){}
};
typedef lnode* pNode;
class clist
{
private :
static pNode avail;
static int cl_num;
pNode head;
size_t size;
public:
clist():head(NULL), size(0){ ++clist::cl_num;}
~clist(){
cout<<__FUNCTION__<<endl;
if(0==--cl_num) removeFrom(avail);
removeAll();
}
clist(clist& orig);
clist& operator=(clist& rhs);
const size_t& getSize()const { return size;}
pNode& getNodePtr(const int& n) throw(const char*);
void insertAt(const T& data, const int& n) throw(const char*);
// const T& getDataAt(const int& n) const throw(const char*);
// const T operator[](const int& n)const throw(const char*);
T& operator[](const int& n) throw(const char*);
void add(const T& data);
void removeAt(const int&n) throw(const char*);
void removeFrom(pNode& ptr);
const int find(const T& data, const int&startN=0) throw(const char*);
void removeAll();
bool isEmpty() { return 0==size;}
void travel();
friend ostream& operator<<(ostream& os, const clist& cl);
pNode get_node(const T& data);
// 测试函数
void showNUM()
{
cout<<clist::cl_num<<endl;
}
void showAvail()
{
cout<<"avail:";
pNode tmp=avail;
while(tmp)
{
cout<<tmp->data<<" ";
tmp=tmp->next;
}
cout<<endl;
}
};
#endif
cpp :
#include "clist.h"
pNode clist::avail=NULL;
int clist::cl_num=0;
clist::clist(clist& orig):head(NULL),size(0)
{
++clist::cl_num; //更新static clist::cl_num
this->size=0;
for(int i=0;i<orig.size;i++)
this->add(orig[i]);
}
clist& clist::operator=(clist& rhs)
{
this->removeAll(); //赋值函数对旧值处理
this->size=0;
for(int i=0;i<rhs.size;i++)
this->add(rhs[i]);
}
//返回值是第n个节点的地址引用-> 就是第n-1个节点的链域的引用
//n:0~size -> 有连个指针指向头节点,head 和 第 size-1的链域
// n=0 n=size 的返回值是相同的
pNode& clist::getNodePtr(const int& n) throw(const char*)
{
if(n<0 || n>size) throw "超出节点范围";
if(0==n) return head;
pNode Ptr=head;
for(int i=1;i<=n-1;++i) Ptr=Ptr->next;
return Ptr->next;
}
// 在第n个节点前插入,就是修改第n-1个节点的链域
// 与单链表不同的一点只有在插入到第一个元素的时候,需要更新两个指针:
// 1)head 值 2) 最后一个元素的链域
void clist::insertAt(const T& data, const int& n) throw(const char*)
{
if(n<0 || n>size) throw "超出节点范围";// n==size --> 追加到末尾
pNode newNode = this->get_node(data);
if(0==n) this->getNodePtr(size)=newNode; //更新最后节点的链域
pNode& ptr=getNodePtr(n);
newNode->next = ptr;
ptr = newNode;
++this->size;
}
T& clist::operator[](const int& n) throw(const char*) //非const成员访问,并可以修改返回值
{
if(n<0 || n>=size) throw "超出节点范围";
return getNodePtr(n)->data;
}
void clist::add(const T& data)
{
this->insertAt(data, this->size);
}
//释放节点,返回给avail(回收空间)
//回收一个节点,只要把节点查到类的静态链 avail头部就行了
void clist::removeAt(const int&n) throw(const char*)
{
if(n<0 || n>=size) throw "超出节点范围";
pNode& ptr=getNodePtr(n);
pNode tmp=ptr;
ptr=ptr->next;
tmp->next=avail;
avail=tmp;
}
// 用于释放avail的空间 <-- 已申请的节点真正的释放
// 当没有链表存在的时候,就释放类静态空间的可利用空间
void clist::removeFrom(pNode& ptr)
{
cout<<"real delete clist!"<<endl;
pNode tmp=ptr;
while(ptr)
{
ptr=ptr->next;
delete[] tmp;
tmp=ptr;
}
//过程中把avail置为NULL
}
const int clist::find(const T& data, const int& startN) throw(const char*)
{
if(startN<0 ||startN>=size) return -1;
pNode ptr = getNodePtr(startN);
int i=startN;
while(ptr){
if(data==ptr->data) return i;
ptr=ptr->next;
++i;
if(ptr==head) break;
}
return -1;
}
//删除某条循环链表,就是把它回收到avail中
//只需注意两点:被回收的链表第一个节点的链域
// 指向avail; 而把avail值替换为
// 回收链表中第二个节点的首地址
void clist::removeAll()
{
if(!head) return;
pNode tmp=head->next;
head->next=clist::avail;
clist::avail=tmp;
head=NULL; //链表为空
size=0; //error1
}
void clist::travel()
{
pNode ptr=head;
while(ptr)
{
cout<<ptr->data<<" ";
ptr=ptr->next;
if(ptr==head) break;
}
cout<<endl;
}
ostream& operator<<(ostream& os, const clist& cl)
{
pNode ptr=cl.head;
while(ptr)
{
os<<ptr->data<<" ";
ptr=ptr->next;
if(ptr==cl.head) break;
}
return os;
}
pNode clist::get_node(const T& data)
{
if(!clist::avail) return new lnode(data);
avail->data=data;
pNode rNode=avail;
avail=avail->next;
return rNode;
}
测试:
#include "clist.h"
int main()
{
try{
clist cl1;
cl1.add(1);
cl1.add(2);
cl1.add(3);
cout<<"cl1.find(1):"<<cl1.find(1)<<endl;
cout<<"cl1.find(2):"<<cl1.find(2)<<endl;
cout<<"cl1.find(4):"<<cl1.find(4)<<endl;
cl1.insertAt(5,0);
cl1.travel();
cout<<"cl1.find(5):"<<cl1.find(5)<<endl;
cout<<"cl1.size:"<<cl1.getSize()<<endl;
cl1.insertAt(6,4);
cl1.travel();
cout<<"cl1.find(6):"<<cl1.find(6)<<endl;
cout<<cl1[4]<<endl;
clist cl2=cl1;
cl2.removeAll();
cl1.showAvail();
cl1.travel();
clist cl3;
cl3=cl2;
cl1.travel();
cl1.showAvail();
cl1.removeAt(3);
cl1.travel();
cl1.showAvail();
}catch(const char* e)
{
cout<<e<<endl;
}
return 0;
}