数据结构与算法(C++实现)学习笔记(六)

循环链表和双向链表

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 &current->data;
	else return 0;
}
template<class Type>
Type* ListIterator<Type>::Next()
{
	current = current->link;
	if(current == list.first)//先前移动,回到空的表头
		current = current->link;//再移一次
	return &current->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;
}

参考视频:

https://www.bilibili.com/video/av31763085/?p=17

https://www.bilibili.com/video/av31763085/?p=18

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值