数据结构(C++)笔记5 (列表)

列表

头、尾节点

在这里插入图片描述
List对象的内部组成及逻辑结构如图所示,其中私有的头节点( header) 和尾节点
( trailer) 始终存在,但对外并不可见。对外部可见的数据节点如果存在,则其中的第一个和最后一个节点分别称作首节点( first node) 和末节点( last node) 。
就内部结构而言, 头节点紧邻于首节点之前, 尾节点紧邻于末节点之后。这类经封装之后从外部不可见的节点, 称作哨兵节点( sentinel node) 。

默认构造方法

创建List对象时,默认构造方法将调用如代码所示的统一初始化过程init(), 在列表
内部创建一对头、尾哨兵节点,并适当地设置其前驱、后继指针构成一个双向链表。

示例程序(初始化过程)

template <typename T> void List<T>::init() {
    
     //列表初始化,在创建列表对象时统一调用
   header = new ListNode<T>; //创建头哨兵节点
   trailer = new ListNode<T>; //创建尾哨兵节点
   header->succ = trailer; header->pred = NULL;
   trailer->pred = header; trailer->succ = NULL;
   _size = 0; //记录规模
}

该链表对外的有效部分初始为空, 哨兵节点对外不可见, 此后引入的新节点都将陆续插入于这一对哨兵节点之间
在这里插入图片描述

由秩到位置的转换

通过重载操作符“[]” ,提供一个转换接口。

template <typename T> //重载下标操作符,以通过秩直接访问列表节点(虽方便,效率低,需慎用)
T& List<T>::operator[] ( Rank r ) const {
    
     //assert: 0 <= r < size
   ListNodePosi(T) p = first(); //从首节点出发
   while ( 0 < r-- ) p = p->succ; //顺数第r个节点即是
   return p->data; //目标节点,返回其中所存元素
}

查找

template <typename T> //在无序列表内节点p(可能是trailer)的n个(真)前驱中,找到等于e的最后者
ListNodePosi(T) List<T>::find ( T const& e, int n, ListNodePosi(T) p ) const {
    
    
   while ( 0 < n-- ) //(0 <= n <= rank(p) < _size)对于p的最近的n个前驱,从右向左
      if ( e == ( p = p->pred )->data ) return p; //逐个比对,直至命中或范围越界
   return NULL; //p越出左边界意味着区间内不含e,查找失败
} //失败时,返回NULL

插入

template <typename T> ListNodePosi(T) List<T>::insertAsFirst ( T const& e )
{
    
      _size++; return header->insertAsSucc ( e );  } //e当作首节点插入

template <typename T> ListNodePosi(T) List<T>::insertAsLast ( T const& e )
{
    
      _size++; return trailer->insertAsPred ( e );  } //e当作末节点插入

template <typename T> ListNodePosi(T) List<T>::insertA ( ListNodePosi(T) p, T const& e )
{
    
      _size++; return p->insertAsSucc ( e );  } //e当作p的后继插入(After)

template <typename T> ListNodePosi(T) List<T>::insertB ( ListNodePosi(T) p, T const& e )
{
    
      _size++; return p->insertAsPred ( e );  } //e当作p的前驱插入(Before)

基于复制的构造

copyNode()

template <typename T> //列表内部方法:复制列表中自位置p起的n项
void List<T>::copyNodes ( ListNodePosi(T) p, int n ) {
    
     //p合法,且至少有n-1个真后继节点
   init(); //创建头、尾哨兵节点并做初始化
   while ( n-- ) {
    
     insertAsLast ( p->data ); p = p->succ; } //将起自p的n项依次作为末节点插入
}

在输入参数合法的前提下,copyNodes()首先调用init()方法, 创建头、尾哨兵节点并做相应的初始化处理,然后自p所指节点起,从原列表中取出n个相邻的节点,并逐一作为末节点插至新列表中。

template <typename T> //复制列表中自位置p起的n项(assert: p为合法位置,且至少有n-1个后继节点)
List<T>::List ( ListNodePosi(T) p, int n ) {
    
     copyNodes ( p, n ); }

template <typename T> //整体复制列表L
List<T>::List ( List<T> const& L ) {
    
     copyNodes ( L.first(), L._size ); }

template <typename T> //复制L中自第r项起的n项(assert: r+n <= L._size)
List<T>::List ( List<T> const& L, int r, int n ) {
    
    
   ListNodePosi(T) p = L.first();
   while ( 0 < r-- ) p = p->succ;
   copyNodes ( p, n );
}

删除

在列表中删除指定节点p的算法。

template <typename T> T List<T>::remove ( ListNodePosi(T) p ) {
    
     //删除合法节点p,返回其数值
   T e = p->data; //备份待删除节点的数值(假定T类型可直接赋值)
   p->pred->succ = p->succ; p->succ->pred = p->pred; //后继、前驱
   delete p; _size--; //释放节点,更新规模
   return e; //返回备份的数值
}

在这里插入图片描述

析构

template <typename T> List<T>::~List() //列表析构器
{
    
     clear(); delete header; delete trailer; } //清空列表,释放头、尾哨兵节点
template <typename T> int List<T>::clear() {
    
     //清空列表
   int oldSize = _size;
   while ( 0 < _size ) remove ( header->succ ); //反复删除首节点,直至列表变空
   return oldSize;
}

唯一化

template <typename T> int List<T>::deduplicate() {
    
    
   int oldSize = _size; ListNodePosi(T) p = first(); ListNodePosi(T) q = NULL;
   for ( Rank r = 0; p != trailer; p = p->succ, q = find ( p->data, r, p ) )
      q ? remove ( q ): r++; //r为无重前缀的长度
   return oldSize - _size; //即被删除元素总数
}

遍历

template <typename T> void List<T>::traverse ( void ( *visit ) ( T& ) ) //借助函数指针机制遍历
{
    
      for ( ListNodePosi(T) p = header->succ; p != trailer; p = p->succ ) visit ( p->data );  }

template <typename T> template <typename VST> //元素类型、操作器
void List<T>::traverse ( VST& visit ) //借助函数对象机制遍历
{
    
      for ( ListNodePosi(T) p = header->succ; p != trailer; p = p->succ ) visit ( p->data );  }

猜你喜欢

转载自blog.csdn.net/jlm7689235/article/details/108072350