双向循环链表
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 双向链表
20
② 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; }
//当前结点 //下一结点 //已是空表 //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
… …
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; //左、右指针 };
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)
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) ;
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 双向链表
1
双向链表
• 双向链表 是指在前驱和后继方向都能游历(遍历)的 链表。 • 在双向链表中,每个结点有两个指针域,一个指向直 接后继元素结点,另一个指向直接前趋元素结点。
2.7 双向链表
2
双向链表结点结构
存储数 据元素
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
左指针 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
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; //输出双链表 };
2.7 双向链表
6
双向循环链表
• 双向链表通常采用带表头结点的循环链表形式。
header
a1
非空表
a2
… …
an
header
空表
2.7 双向链表
7
双向循环链表类定义—双向循环链表类
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; //输出双链表 };