循环链表

/*
 * =====================================================================================
 *
 *       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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值