循环链表和双向链表
1. 循环链表
1.1 循环链表的基本概念
循环链表是另一种形式的链式存贮结构。它的特点是表中最后一个结点的指针域(空指针)指向头节点,整个链表形成一个环。
(1)一般来说,为了方便操作,都会设一个头结点,所以带有头结点的循环链表为空链表时如下图所示:
(2)对于非空的循环链表就如下图所示:
2. 代码示例
#ifndef MYLIST_H
#define MYLIST_H
#include<iostream>
template <class Type> class List;
template <class Type> class ListIterator;
template <class Type>
class ListNode
{
friend class List<Type>;
friend class ListIterator<Type>;
private:
Type data;
ListNode* link;
ListNode(Type);
ListNode() {};//增加一个默认的构造函数
};
template <class Type>
class List
{
friend class ListIterator<Type>;
public:
List() { first = new ListNode<Type>; first->link = first; };
void Insert(Type);
void Delete(Type);
private:
ListNode<Type> *first;
};
template<class Type>
class ListIterator
{
public:
ListIterator(const List<Type> &l) :list(l), current(l.first->link){}
bool NotNull();
bool NextNotNull();
Type *First();
Type *Next();
private:
const List<Type> &list;
ListNode<Type> *current;
};
template <class Type>
bool ListIterator<Type>::NotNull()
{
if (current != list.first) return true;
else return false;
}
template <class Type>
bool ListIterator<Type> ::NextNotNull()
{
if (current->link != list.first) return true;
else return false;//当前节点的下一个等于first,则返回false
}
template<class Type>
Type* ListIterator<Type>::First()
{
//当前节点不等于first,则返回当前节点数据
if (current != list.first) return ¤t->data;
else return 0;
}
template<class Type>
Type* ListIterator<Type>::Next()
{
current = current->link;
if(current == list.first)//先前移动,回到空的表头
current = current->link;//再移一次
return ¤t->data;//返回他的数据域
}
template <class Type>
ListNode<Type>::ListNode(Type element)
{
data = element;
link = 0;//新的节点,无下个节点
}
template<class Type>
void List<Type>::Insert(Type k)
{
ListNode<Type>* newnode = new ListNode<Type>(k);
newnode->link = first->link;//新的节点的下一个等于表头的下一个
first->link = newnode;
}
template<class Type>
void List<Type>::Delete(Type k)
{
ListNode<Type>* previous = first;//first是循环列表的表头
ListNode<Type>* current;//current 用于循环
for (current = first->link;
(current != first) && current->data != k;//是否找到数据或回到开头
previous = current, current = current->link) ;//空循环
if (current != first){
previous->link = current->link;
delete current;
}
}
#endif
#include<iostream>
#include"Mylist.h"//自己的链表
using namespace std;
int main()
{
cout << "使用自己设计的链表和迭代器:" << endl;
List<int> intlist;
intlist.Insert(5);
intlist.Insert(15);
intlist.Insert(25);
intlist.Insert(35);
ListIterator<int> li(intlist);
if (li.NotNull()) {
cout << *li.First();
while (li.NextNotNull())
cout << "->" << *li.Next();
cout << endl;
}
cout << "测试为循环列表:" << endl;
cout << *li.First() << endl;
cout << *li.Next() << endl;
cout << *li.Next() << endl;
cout << *li.Next() << endl;
cout << *li.Next() << endl;
cout << *li.Next() << endl;
cout << *li.Next() << endl;
cout << *li.Next() << endl;
cout << *li.Next() << endl;
return 0;
}
2.双向列表
2.1 双向列表的基本概念
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
三个域:左链域 llink、右链域 rlink、数据域
可以是循环链表,一般有表头结构:
2.2 双链表的实现
因为是为了学习双链表的原理,代码写的不够严谨。
#include<iostream>
using namespace std;
class DblList;
class DblListNode
{
friend class DblList;
public:
int data;
DblListNode *llink, *rlink;//左右指针
};
class DblList
{
public:
DblList()
{
first = new DblListNode();
first->llink = first->rlink = first;//左右指针均指向自己
};
void Insert(DblListNode*,DblListNode*);//一个节点插入到另一节点右边
void Delete(DblListNode*);
//private:
public:
DblListNode *first;//指向表头结构
};
void DblList::Insert(DblListNode*p, DblListNode*x)//4个指针需要调整
{
p->llink = x;
p->rlink = x->rlink;
x ->rlink->llink = p;
x->rlink = p;
}
void DblList::Delete(DblListNode*x)
{
if (x == first)
cerr << "Deletion of head node is not permitted" << endl;
else {
x->llink->rlink = x->rlink;
x->rlink->llink = x->llink;
}
}
int main()
{
DblList intlist;
DblListNode node1, node2, node3, node4, node5;
node1.data = 10;
node2.data = 20;
node3.data = 30;
node4.data = 40;
node5.data = 50;
intlist.Insert(&node1, intlist.first);
intlist.Insert(&node2, intlist.first);
intlist.Insert(&node3, intlist.first);
intlist.Insert(&node4, intlist.first);
intlist.Insert(&node5, intlist.first);
intlist.Delete(&node3);
cout << intlist.first->rlink->data << endl;
cout << intlist.first->rlink->rlink->data << endl;
cout << intlist.first->rlink->rlink->rlink->data << endl;
cout << intlist.first->rlink->rlink->rlink->rlink->data << endl;
cout << intlist.first->rlink->rlink->rlink->rlink->llink->data << endl;
return 0;
}
参考视频: