通常在循環鏈表的第一個節點前附加一個特殊的節點來作爲標記,這個節點稱爲循環鏈表的頭結點,頭結點的數據域爲空域,或者按照需要設定。
在這裏,我們將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;
}