双向循环链表
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
p->right->left= y; p->right=y; n++; return * this; }
2.7 双向链表
//表长度加1
17
双向循环链表的删除
k header a1 … … k ak ① ak-1 q a ak1 ②
aa2 k+1 ak+1
k … … an
① q->left->right=q->right
current
while (current->data != x) { current = current->next; index++; }
2.7 双向链表
13
查找元素x位置算法
template<class Type> int dbclist<Type>::locate(const Type& x) const { dnode<Type> *current = header->right; //current指向位置1 int index = 1; // index记录元素位置 header->data = x; //用于循环终止条件 while (current->data != x) { //找元素x所在的结点 current = current->right; index++; } return ((current==header) ? 0 : index) ;
… …
an right_end
2.7 双向链表
4
双向链表类定义—结点类
template <class Type> class dblist; //前视类定义 template <class Type> class dnode { friend class dblist<Type>; //友类声明 private: Type data; //数据 dnode<Type> *left, *right; //左、右指针 };
链表指针的方向?
单链表? 循环链表?
单向的 优点?
双向的 双向链表
2.7 双向链表
1
双向链表
• 双向链表 是指在前驱和后继方向都能游历(遍历)的 链表。 • 在双向链表中,每个结点有两个指针域,一个指向直 接后继元素结点,另一个指向直接前趋元素结点。
2.7 双向链表
2
双向链表结点结构
存储数 据元素
2.7 双向链表
6
双向循环链表
• 双向链表通常采用带表头结点的循环链表形式。
header
a1
非空表
a2
… …
an
header
空表
2.7 双向链表
7
双向循环链表类定wk.baidu.com—双向循环链表类
template <class Type> class dbclist { private: int n; //表长度 dnode<Type> *header; //表头,表尾指针 public: dbclist ( ); //构造函数 ~dbclist ( ) {erase();delete header}; //析构函数 void erase(); //删除表结点 bool empty( ) const {return n==0;} //测试表是否为空 int size( ) const {return n;} //表的长度 bool retrieve(int k, Type& x) const; //查找表位置k处的元素 int locate(const Type& x) const; //计算元素x在表中的位置 dblist<Type>& insert(int k, const Type& x); //插入结点 dblist<Type>& erase(int k, Type& x); //删除结点 void print_list(ostream& out) const; //输出双链表 };
//current指向头结点返回0,否则返回位置号
}
2.7 双向链表
14
双向循环链表的插入
循环链表的插入是指在位置k后插入新结点
k
k<0
k
k
k
k
k>n
header
a1
… …
ak
… …
an
2.7 双向链表
15
双向循环链表的插入演示
k header a1 … … k ak
ak+1
k … … an
ak p ① y->left=p
2.7 双向链表
20
2.7 双向链表
12
查找元素x位置
• 基本思想:从位置1结点开始依次向后扫描,直到找到表中 元素x,若找到则返回位置数,否则返回0。
index=n+1
index=1
header
x
a1
… …
index=k
x ak
… …
index=n
an
current current current==header
current
header y
2.7 双向链表
空表
9
析构函数—erase()函数
template<class Type> void dbclist<Type>::erase( ) {
dnode<Type> *current; dnode<Type> *next; if (header==0) return; current=header->right; while (!empty()) { next=current->right; delete current; n--; current=next; }
index=1
header
a1
current
… …
index=k
ak data
… …
an
current
while (index < k ){ current = current->next; index++;}
2.7 双向链表
11
查找位置k元素并存于x中算法
template<class Type> bool dbclist<Type>::retrieve(int k, Type& x) const { if (k < 1 || k > n) return false; //k值越界 dnode<Type> *current=header->right; //current从第1个元素开始 int index = 1; while (index < k ) { //找表中第k个元素 current = current->right; index++; } x = current->data; //取第k个元素值赋予x return true; }
2.7 双向链表
5
双向链表类定义—双向链表类
template <class Type> class dblist { private: int n; //表长度 dnode<Type> *left_end, *right_end; //表头,表尾指针 public: dblist ( ) {left_end=right_end = 0;}; //构造函数 ~dblist ( ); //析构函数 bool empty( ) const {return n==0;} //测试表是否为空 int size( ) const {return n;} //表的长度 bool retrieve(int k, Type& x) const; //查找表位置k处的元素 int locate(const Type& x) const; //计算元素x在表中的位置 dblist<Type>& insert(int k, const Type& x); //插入结点 dblist<Type>& erase(int k, Type& x); //删除结点 void print_list(ostream& out) const; //输出双链表 };
ak+1 a1
④
①
x y
② ③ ③ p->right->left=y
② y->right=p->right ④ p->right=y
2.7 双向链表
16
双向循环链表的插入算法
template<class Type> dbclist<Type>& dbclist<Type>::insert(int k, const Type& x)
② q->right->left=q->left
2.7 双向链表
18
双向循环链表的删除算法
template<class Type> dbclist<Type>& dbclist<Type>::erease(int k, Type& x) { if (k < 1 || k > n) throw out_bounds(); // k值越界 dnode<Type> *q = header->right; // 指针q指向第k个元素 for (int index=1; index<k; index++) q=q->right; q->left->right=q->right; //q指向的第k个元素被删除 q->right->left=q->left; x = q->data; // 用x保存原表中第k个元素 delete q; // 释放第k个元素结点 n--; // 表长度减1 return *this; }
左指针 left
数据域 data
右指针 right
存储前驱 结点地址
结点图示
存储后继 结点地址
2.7 双向链表
3
双向链表结构
• 双向链表中有指向头结点和尾结点的两个指针 left_end和right_end。 • 双向链表中双指针的设置,可以快速的找到某 结点的前趋和后继结点。 a1 left_end a2 a3
{ //位置k后插入结点 if (k < 0||k > n) throw out_bounds( ); // k值越界 dnode<Type> *p =header; // 指针p初始化为头结点 for (int index=1; index<=k ; index++) p=p->right; // 搜索位置k dnode<Type> *y=new dnode<Type>; //申请新结点y y->data = x; y->left =p; y->right=p->right; //插入结点y
//当前结点 //下一结点 //已是空表 //current初始化 //若表非空则依次删除表中结点
//n实际控制循环次数
}
header
a1 current next current
2.7 双向链表
a2 current next
… …
an
10
current next
查找位置k元素并存于x中
• 基本思想:从第1个结点开始依次向后扫描,直到找到位置k 上的元素,并存于x中,且返回ture,位置k无效返回false。 k k k
2.7 双向链表
19
双向循环链表的输出算法
template<class Type> void dbclist<Type>::print_list(ostream& out) const { dnode<Type> * current; for (current=header->right; //从第1个结点开始 current!=header; //到头结点为止 current=current->right) //依次将current后移 out << current->data << " "; }
2.7 双向链表
8
构造函数—仅头结点
template<class Type> dbclist<Type>::dbclist( ) { dnode<Type> *y = new dnode<Type>; //申请新结点y y->left=y; y->right=y; //构建双向循环链 header=y; //表中只有一个哨兵结点 n=0; //空表 }