【数据结构(邓俊辉)学习笔记】列表01——从向量到列表

文章目录

  • 0.概述
  • [1. 从向量到列表](#1. 从向量到列表)
    • [1.1 从静态到动态](#1.1 从静态到动态)
    • [1.2 从向量到列表](#1.2 从向量到列表)
    • [1.3 从秩到位置](#1.3 从秩到位置)
    • [1.4 列表](#1.4 列表)
  • [2. 接口](#2. 接口)
    • [2.1 列表节点](#2.1 列表节点)
      • [2.1.1 ADT接口](#2.1.1 ADT接口)
      • [2.1.2 ListNode模板类](#2.1.2 ListNode模板类)
    • [2.2 列表](#2.2 列表)
      • [2.2.1 ADT接口](#2.2.1 ADT接口)
      • [2.2.2 List模板类](#2.2.2 List模板类)

0.概述

学习了向量,再介绍下列表。先介绍下列表里的概念和语义,这个对理解列表接口还是比较重要的。

1. 从向量到列表

1.1 从静态到动态

1.2 从向量到列表

注意:首末节点描述。

1.3 从秩到位置


对数据结构的访问方式,应与其存储策略相一致。此时,既然继续延用循秩访问的方式已非上策,就应更多地习惯于通过位置,来指代并访问动态存储结构中的数据元素。

1.4 列表

与向量一样,列表也是由具有线性逻辑次序的一组元素构成的集合:
~~~~~~~~~~~~~~~~~~~~~~~~ L = { a0, a1, ..., an-1 }

列表是链表结构的一般化推广,其中的元素称作节点(node),分别由特定的位置或链接指代。与向量一样,在元素之间,也可定义前驱、直接前驱,以及后继、直接后继等关系;相对于任意元素,也有定义对应的前缀、后缀等子集。

2. 接口

2.1 列表节点

2.1.1 ADT接口

###

2.1.2 ListNode模板类

cpp 复制代码
using Rank = unsigned int; //秩

template <typename T> struct ListNode;
template <typename T> using ListNodePosi = ListNode<T>*; //列表节点位置

template <typename T> 
struct ListNode { //列表节点模板类(以双向链表形式实现)
// 成员
   T data; ListNodePosi<T> pred, succ; //数值、前驱、后继
// 构造函数
   ListNode() {} //针对header和trailer的构造
   ListNode ( T e, ListNodePosi<T> p = NULL, ListNodePosi<T> s = NULL )
      : data( e ), pred( p ), succ( s ) {} //默认构造器
// 操作接口
   ListNodePosi<T> insertAsPred( T const& e ); //紧靠当前节点之前插入新节点
   ListNodePosi<T> insertAsSucc( T const& e ); //紧随当前节点之后插入新节点
};

2.2 列表

2.2.1 ADT接口

领会下宏观接口,具体接口后面会做介绍。

分别针对有序和无序列表,提供了去重操作的两个版本(deduplicate()和uniquify()),以及查找操作的两

个版本(find()和search())。与向量一样,有序列表的唯一化,比无序列表效率更高。

由于只能通过位置指针以局部移动的方式访问节点,尽管有序列表中节点在逻辑上始终按照大小次序排列,其查找操作的效率并没有实质改进。

二者的效率完全一致:在最好情况下,均只需O(1)时间;在最坏情况下,均需要O(n)时间;平均而言,二者均需O(n)时间。

2.2.2 List模板类

头尾接口对外不可见,非常重要。

cpp 复制代码
#pragma once

#include "listNode.h" //引入列表节点类

template <typename T> class List { //列表模板类

private:
   Rank _size; ListNodePosi<T> header, trailer; //规模、头哨兵、尾哨兵

protected:
   void init(); //列表创建时的初始化
   Rank clear(); //清除所有节点
   void copyNodes( ListNodePosi<T>, Rank ); //复制列表中自位置p起的n项
   ListNodePosi<T> merge( ListNodePosi<T>, Rank, List<T>&, ListNodePosi<T>, Rank ); //归并
   void mergeSort( ListNodePosi<T>&, Rank ); //对从p开始连续的n个节点归并排序
   void selectionSort( ListNodePosi<T>, Rank ); //对从p开始连续的n个节点选择排序
   void insertionSort( ListNodePosi<T>, Rank ); //对从p开始连续的n个节点插入排序
   void radixSort( ListNodePosi<T>, Rank ); //对从p开始连续的n个节点基数排序

public:
// 构造函数
   List() { init(); } //默认
   List( List<T> const& L ); //整体复制列表L
   List( List<T> const& L, Rank r, Rank n ); //复制列表L中自第r项起的n项
   List( ListNodePosi<T> p, Rank n ); //复制列表中自位置p起的n项
   // 析构函数
   ~List(); //释放(包含头、尾哨兵在内的)所有节点
// 只读访问接口
   Rank size() const { return _size; } //规模
   bool empty() const { return _size <= 0; } //判空
   ListNodePosi<T> operator[]( Rank r ) const; //重载,支持循秩访问(效率低)
   ListNodePosi<T> first() const { return header->succ; } //首节点位置
   ListNodePosi<T> last() const { return trailer->pred; } //末节点位置
   bool valid( ListNodePosi<T> p ) //判断位置p是否对外合法
   { return p && ( trailer != p ) && ( header != p ); } //将头、尾节点等同于NULL
   ListNodePosi<T> find( T const& e ) const //无序列表查找
   { return find( e, _size, trailer ); }
   ListNodePosi<T> find( T const& e, Rank n, ListNodePosi<T> p ) const; //无序区间查找
   ListNodePosi<T> search( T const& e ) const //有序列表查找
   { return search( e, _size, trailer ); }
   ListNodePosi<T> search( T const& e, Rank n, ListNodePosi<T> p ) const; //有序区间查找
   ListNodePosi<T> selectMax( ListNodePosi<T> p, Rank n ); //在p及其n-1个后继中选出最大者
   ListNodePosi<T> selectMax() { return selectMax( header->succ, _size ); } //整体最大者
// 可写访问接口
   ListNodePosi<T> insertAsFirst( T const& e ); //将e当作首节点插入
   ListNodePosi<T> insertAsLast( T const& e ); //将e当作末节点插入
   ListNodePosi<T> insert( ListNodePosi<T> p, T const& e ); //将e当作p的后继插入
   ListNodePosi<T> insert( T const& e, ListNodePosi<T> p ); //将e当作p的前驱插入
   T remove( ListNodePosi<T> p ); //删除合法位置p处的节点,返回被删除节点
   void merge( List<T>& L ) { merge( header->succ, _size, L, L.header->succ, L._size ); } //全列表归并
   void sort( ListNodePosi<T>, Rank ); //列表区间排序
   void sort() { sort( first(), _size ); } //列表整体排序
   Rank dedup(); //无序去重
   Rank uniquify(); //有序去重
   void reverse(); //前后倒置(习题)
// 遍历
   void traverse( void ( * )( T& ) ); //依次实施visit操作(函数指针)
   template <typename VST> void traverse( VST& ); //依次实施visit操作(函数对象)
}; //List

#include "List_implementation.h"
cpp 复制代码
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; //记录规模
}
相关推荐
守护者17016 分钟前
JAVA学习-练习试用Java实现“使用Arrays.toString方法将数组转换为字符串并打印出来”
java·学习
学会沉淀。25 分钟前
Docker学习
java·开发语言·学习
Rinai_R40 分钟前
计算机组成原理的学习笔记(7)-- 存储器·其二 容量扩展/多模块存储系统/外存/Cache/虚拟存储器
笔记·物联网·学习
吃着火锅x唱着歌40 分钟前
PHP7内核剖析 学习笔记 第四章 内存管理(1)
android·笔记·学习
ragnwang43 分钟前
C++ Eigen常见的高级用法 [学习笔记]
c++·笔记·学习
yuanManGan1 小时前
数据结构漫游记:静态链表的实现(CPP)
数据结构·链表
胡西风_foxww1 小时前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
火星机器人life2 小时前
基于ceres优化的3d激光雷达开源算法
算法·3d
Web阿成2 小时前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript