您的位置:首页 > 其它

带表头的单循环链表的实现

2015-07-03 20:39 357 查看
通常在循环链表的第一个节点前附加一个特殊的节点来作为标记,这个节点称为循环链表的头结点,头结点的数据域为空域,或者按照需要设定。



在这里,我们将a1节点的地址设为first,头结点仅当作特殊标记。如果不想增加头结点,也可以实现单循环链表。

本篇的单循环链表是根据上篇《单链表的实现》上稍作修改而来,有什么好的建议请指点我!

1.头文件

#ifndef CHAIN_H
#define CHAIN_H

#include<iostream>
//带头节点的循环链表,头结点是空表
template<class T>
class chainnode
{
template<class T>
friend class chain;
public:
chainnode()   //循环链表设置默认构造函数对数据域不作初始化
{
next = nullptr;//初始化节点时,将该节点指向自己
}
~chainnode()
{

}
void setdata(const T& dat)
{
data = dat;
}
public:
T getdata()
{
return data;
}
chainnode<T>* getnext()
{
return next;
}
private:
T data;
chainnode<T>* next;
};

template<class T>
class chain
{

public:
chain()
{
head= new chainnode < T > ; //单独开辟一个节点当作循环链表的头节点,且头结点不存储数据
length = 0;
head->next = head;
first = nullptr;
}
~chain()
{
chainnode<T>* temp=head->next;
while (temp!=head)
{
chainnode<T>* curr = temp;
temp = temp->next;
delete curr;
}
delete head;
}

public:
bool isempty()   //当循环链表中只存在表头的时候,为空
{
return first == nullptr;
}
chainnode<T>* getfirst()
{
return first;
}

chainnode<T>* gethead()
{
return head;
}

void deletenode(int pos);
int  getlength();
void insertbefore(T dat, int pos);
void insertafter(T dat, int pos);
T find(int pos);
private:
chainnode<T>* first; //指向第一个有意义的节点
chainnode<T>* head; //头结点,特殊标记
int length;
};

template<class T>
void chain<T>::insertbefore(T dat, int pos)  //在pos位置前面插入一个元素
{
if (pos< 0 || pos>length)
{
std::cout << "输入的位置数错误" << endl;
exit(1);
}

chainnode<T>* now = new chainnode < T >;
now->data = dat;
if (first == nullptr)  //如果循环链表只有表头,为空表
{
first = now;
head->next = first;
first->next = head;
++length;
}
else
{
chainnode<T>* pp = first;
for (int i = 1; i < pos - 1 && pp; ++i)
pp = pp->next;
if (pp)
{
if (pos == 1)
{
now->next = first;
head->next = now;
first = now;
}
else
{
now->next = pp->next;
pp->next = now;
}
++length;
}
}
}

template<class T>
void chain<T>::insertafter(T dat, int pos)
{
if (pos < 0 || pos>length)
{
std::cout << "输入的位置数错误" << endl;
exit(1);
}

chainnode<T>* now = new chainnode < T >;
now->data = dat;
if (first == nullptr)
{
first = now;
head->next = now;
first->next = head;
++length;
}
else
{
chainnode<T>* pp = first;
for (int i = 1; i < pos && pp; ++i)
pp = pp->next;
if (pp)
{
if (pos == length)
{
now->next = head;
pp->next = now;

}
else
{
now->next = pp->next;
pp->next = now;
}
++length;
}
}
}
template<class T>
T chain<T>::find(int pos)
{
if (first)
{
if (pos<0 || pos>length)
{
std::cout << "输入的位置数错误" << endl;
exit(1);
}
chainnode<T>* curr=first;
for (int i = 1; i < pos; ++i)
curr = curr->next;
return curr->data;
}
}
template<class T>
int chain<T>::getlength()
{
if (first == nullptr)
return  0;
chainnode<T>* current = first;
int len = 0;
while (current!=head)
{
++len;
current = current->next;
}
length = len;
return len;
}

template<class T>
void chain<T>::deletenode(int pos)
{
if (first)
{
if (pos<0 || pos>length)
{
std::cout << "输入的位置数错误" << endl;
exit(1);
}
if (pos == 1)
{
chainnode<T>* temp = first;
head->next = first->next;
first = first->next;
delete temp;
--length;
}
else
{
chainnode<T>* tem = first;
for (int i = 1; i < pos - 1 && tem; ++i) //获得pos前一个元素的地址
tem = tem->next;
if (tem &&tem->next)   //确保第pos个元素存在
{
chainnode<T>* curr = tem->next; //curr是pos位置元素的地址
tem->next = curr->next;
delete curr;
--length;
}
}
}
}

template<class T>
std::ostream& operator <<(std::ostream& out, chain<T>& list)
{
chainnode<T>* cc = list.getfirst();
for (int i = 1; i <= list.getlength(); ++i)
{
out <<cc->getdata() << " ";
cc = cc->getnext();
}
std::cout << std::endl;
return out;
}
#endif


2.main文件

#include<iostream>
#include"chain.h"
using namespace std;

int main()
{
chain<char> liner;
liner.insertafter('A', 0);
liner.insertafter('B', 1);
liner.insertafter('C', 2);
liner.insertafter('D', 3);
liner.insertbefore('E',1);
//*********测试循环链表是否完成********
(liner.gethead())->setdata('H');//用H表示头结点数据,头结点数据默认为空
chainnode<char>* xx = liner.getfirst();
for (int i = 1; i < 10; ++i)
{
cout << xx->getdata() << " ";
xx = xx->getnext();
}
cout << endl;
//*********这段代码目的只为测试********
auto dd = liner.find(3);
cout << dd << endl;
cout<< liner << endl;
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: