c++实现链式表的类模板

在写链表反转的时候很苦恼,感谢这位博主的图http://blog.csdn.net/u013271921/article/details/46382345

然后自己画了几遍,终于是理解了

/*
类模板双向链表,通过一个节点类node和一个链表类chlist来实现,node中包含前驱指针pr,后继指针nx,和数据域data,并且data可接受任意类型的数据
链表类chlist包含逆序创建链表操作,指定位置插入操作,指定位置删除操作,寻找指定位置元素操作和翻转链表等操作,并且包含指向链表的头指针、尾指针和表长
chlist中的成员函数:
														1.Createlist逆序创建链表
														2.insertz指定位置插入
														3.erasez指定位置删除
														4.findz输出并返回指定位置的元素
														5.reversal反转链表
														6.chlist创建空链表
														7.~chlist析构函数
														8.push_front头插
														9.push_back尾插
														10.pop_front头删
														11.pop_back尾删
														12.length输出并返回表长
														13.clear清空链表
在下面的代码中
														1.e代表T类型的元素
														2.i代表位置
作者:chczy
2017/10/16	星期一	下午9:08
*/
#include<iostream>
#include<algorithm>
#include<new>
using namespace std;
template<class T>
struct node {
	node *pr;//前驱指针
	node *nx;//后继指针
	T data;//数据

};//节点类
//双向链表类
template<class T>
class chlist {
public:
	chlist();
	~chlist() { cout <<"destroy chlist. "<< endl; };
	chlist& operator=(const chlist&);
	bool Createlist(int n);//创建空链表
	node<T>* insertz(int i, T e);//在i位置插入元素d
	node<T>* erasez(int i);//删除i位置的元素
	node<T>* findz(int i);//寻找i位置的元素
	node<T>* reversal();//反转链表
	node<T>* push_front(T e);//头插
	node<T>* push_back(T e);//尾插
	node<T>* pop_front();//头删
	node<T>* pop_back();//尾删
	bool empty();//检查链表是否为空
	void clear();//将链表置空
	void display();//输出链表的所有元素
	int length();
private:
	node<T> *head;//头指针
	node<T> *tail;//尾指针
	int len;//表长
};
template<class T>
chlist<T>::chlist()//creat a null list
{
	head = NULL;
	tail = NULL;
	len = 0;
}

template<class T>
bool chlist<T>::Createlist(int n)//不断在表头添加元素,逆序建立链表
{
	if (empty())
	{
		node<T> *L = new node<T>;
		L->pr = NULL;
		L->nx = NULL;
		int i = n;
		while (n--)
		{
			node<T> *p = new node<T>;
			cin >> p->data;
			p->nx = L->nx;//接到后一个节点
			p->pr = L;	  //反连接到头结点L
			L->nx = p;	  //L链接到新节点
			if (i > n + 1)//当连接了2个节点以上时
				p->nx->pr = p;//旧节点反链接到新节点
			if (i == n + 1)//将第一个接入的节点设置为尾节点
				tail = p;
		}
		head = L;//head指向头结点(第一个节点之前的节点)
		len = i;//存表长
		return 1;//创建成功返回1
	}
	else
		return 0;//否则返回0
}

template<class T>
node<T>* chlist<T>::insertz(int i, T e)
{
	if (i > len+1)
	{
		throw"out of range!\n";
	}
	if (i == 1&&len!=0)//如果要插入第一个位置
	{
		node<T>* s=push_front(e);//则执行头插
		return s;
	}
	else if (i == len+1&&len!=0)//如果要插入最后一个位置
	{
		node<T>* s = push_back(e);//则执行尾插
		return s;
	}
	else if (len == 0)
	{
		node<T> *s = new node<T>;
		s->data = e;
		head->nx = s;
		s->pr = head;
		s->nx = NULL;
		tail = s;
		++len;
	}
	else
	{
		node<T>* p = head;
		int j = 0;  
		while (p&&j <= i - 1)
		{
			p = p->nx;
			++j;
		}
		node<T> *s = new node<T>;
		s->data = e;
		(p->pr)->nx = s;
		s->nx = p;
		s->pr = p->pr;
		p->pr = s;
		++len;
		return s;
	}
}

template<class T>
node<T>* chlist<T>::erasez(int i)
{
	if (i > len&&i < 0)
	{
		throw"out of range!\n";
	}
	if (i == 1&&len!=1)
	{
		node<T>* s = pop_front();
		return s;
	}
	else if (i == len&&len != 1)
	{
		node<T>* s = pop_back();
		return s;
	}
	if (len == 1)
	{
		node<T>* s = head->nx;
		head->nx = NULL;
		tail = NULL;
		delete s;
		--len;
		return head;
	}
	else//长度不为1,且删除位置不为头尾,即一般情况
	{
		int j = 0;
		node<T> *p = head;
		while (p&&j <= i - 1)//寻找待删除节点
		{
			p = p->nx;
			++j;
		}
		node<T>* s = p->nx;//s为删除节点的后一节点
		(p->pr)->nx = s;//删除节点的前一节点的后继更新为s
		s->pr = p->pr;//s的前驱更新为删除节点的前一节点
		delete p;//删除p
		--len;//更新长度
		return s;//返回删除节点的后一节点
	}
}

template<class T>
node<T>* chlist<T>::findz(int i)
{
	if (i > len)
	{
		throw"out of range!\n";
	}
	node<T> *p=head;
	int j = 0;
	while (p&&j <= i - 1)
	{
		p = p->nx;
		++j;
	}
	cout <<i<< "位置的元素为:" << endl;
	cout << p->data << endl;
	return p; 
}

template<class T>
chlist<T>& chlist<T>::operator=(const chlist<T>& rhs)
{
	head = rhs.head;
	tail = rhs.tail;
	len = rhs.len;
	return *this;
}

template<class T>
node<T>* chlist<T>::reversal()//有问题
{
	node<T> *NH = NULL;//新头节点指针
	node<T> *Prev = NULL;//前一个指针
	node<T> *Node = head->nx;//节点指针
	tail = head->nx;//原来的头指针变为尾指针
	while (Node != NULL)//不遍历到最后一个(尾空)
	{
		node<T> *Next = Node->nx;
		if (Next == NULL)//Next指向了尾后
		{
			node<T> *p = new node<T>;
			p->pr = NULL;
			p->nx = Node;
			NH = p;
			head = p;//更新头指针,为新的第一节点之前的指针
		}
		Node->nx = Prev;//把Node的后继指针指向Node的元前一位元素
		Node->pr = Next;//把Node的前驱指向Node的元后一位元素
		Prev = Node;//更新Prev
		Node = Next;//更新Next
	}
	return NH;//返回头结点
}

template<class T>
bool chlist<T>::empty()
{
	if (len == 0)
		return 1;
	else
		return 0;
}

template<class T>
void chlist<T>::display()
{
	if (len == 0)
	{
		cout << "null list!" << endl;
		return;
	}
	node<T> *p = head->nx;
	cout << "表中元素为:" << endl;
	while (p != tail)
	{
		cout << p->data << endl;
		p = p->nx;
	}
	cout << p->data << endl;
	cout << "表长为" << len << endl;
}

template<class T>
void chlist<T>::clear()
{
	while (!empty()) { erasez(1);}
}

template<class T>
node<T>* chlist<T>::push_front(T e)//头插
{
	node<T>* s = new node<T>;
	s->data = e;
	s->nx = head->nx;
	head->nx = s;
	s->pr = head;
	(s->nx)->pr = s;
	++len;
	return s;
}
	
template<class T>
node<T>* chlist<T>::push_back(T e)//尾插
{
	node<T>* s = new node<T>;
	s->data = e;
	tail->nx = s;
	s->pr = tail;
	s->nx = NULL;
	tail = s;
	++len;
	return s;
}

template<class T>
node<T>* chlist<T>::pop_front()//头删
{
	node<T>* p = head->nx;//p指向第一个节点
	node<T>* s = p->nx;//s指向第二个节点
	head->nx = p->nx;//头结点的后继更新为第二个节点
	(p->nx)->pr = head;//第二个节点的前驱更新为头结点
	delete p;//删除第一个节点
	--len;//更新长度
	return s;//返回删除后的第一个节点的指针
}

template<class T>
node<T>* chlist<T>::pop_back()//尾删
{
	node<T> *p = tail;//p为最后一个节点
	node<T> *s = tail->pr;//s为倒数第二个节点
	s->nx = NULL;//s节点指向空,变为最后一个节点
	tail = s;//尾节点更新为s
	delete p;//删除p
	--len;//更新长度
	return s;//返回删除后的尾节点的指针s,此时s==tail
}

template<class T>
int chlist<T>::length()
{
	cout << "表长为:" << endl;
	cout << len << endl;
	return len;
}
//by chczy


猜你喜欢

转载自blog.csdn.net/chczy1/article/details/78254931