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


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面向对象程序设计课程作业 1. 请创建一个数据类型为T的链表类模板List,实现以下成员函数: 1) 默认构造函数List(),将该链表初始化为一个空链表(10分) 2) 拷贝构造函数List(const List& list),根据一个给定的链表构造当前链表(10分) 3) 析构函数~List(),释放链表中的所有节点(10分) 4) Push_back(T e)函数,往链表最末尾插入一个元素为e的节点(10分) 5) operator<<()友元函数,将链表的所有元素按顺序输出(10分) 6) operator=()函数,实现两个链表的赋值操作(10分) 7) operator+()函数,实现两个链表的连接,A=B+C(10分) 2. 请编写main函数,测试该类模板的正确性: 1) 用List模板定义一个List类型的模板类对象int_listB,从键盘读入m个整数,调用Push_back函数将这m个整数依次插入到该链表中;(4分) 2) 用List模板定义一个List类型的模板类对象int_listC,从键盘读入n个整数,调用Push_back函数将这n个整数依次插入到该链表中;(4分) 3) 用List模板定义一个List类型的模板类对象int_listA,调用List的成员函数实现A = B + C;(4分) 4) 用cout直接输出int_listA的所有元素(3分) 5) 用List模板定义List类型的模板类对象double_listA, double_listB, double_listC,重复上述操作。(15分) 3. 输入输出样例: 1) 输入样例 4 12 23 34 45 3 56 67 78 3 1.2 2.3 3.4 4 4.5 5.6 6.7 7.8 2) 输出样例 12 23 34 45 56 67 78 1.2 2.3 3.4 4.5 5.6 6.7 7.8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值