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

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

2017-10-16 21:54 239 查看
在写链表反转的时候很苦恼,感谢这位博主的图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
4000
+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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: