List::定义

结点的定义:

typedef int Rank; //秩
#define ListNodePosi(T) ListNode<T>* //列表节点位置

template <typename T> struct ListNode { //列表节点模板类(以双向链表形式实现)
// 成员
   T data; ListNodePosi(T) pred; ListNodePosi(T) 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); //紧随当前节点之后插入新节点
};

链表的定义(这儿用的是双向链表):

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

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

private:
   int _size; ListNodePosi(T) header; ListNodePosi(T) trailer; //规模、头哨兵、尾哨兵

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

public:
// 构造函数
   List() { init(); } //默认
   List(List<T> const & L); //整体复制列表L
   List(List<T> const & L, Rank r, int n); //复制列表L中自第r项起的n项
   List(ListNodePosi(T) p, int n); //复制列表中自位置p起的n项
// 析构函数
   ~List(); //释放(包含头、尾哨兵在内的)所有节点
// 只读访问接口
   Rank size() const { return _size; } //规模
   bool empty() const { return _size<=0; } //判空
   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
   int disordered() const; //判断列表是否已排序
   ListNodePosi(T) find(T const & e) const  //无序列表查找
      { return find(e, _size, trailer); }
   ListNodePosi(T) find(T const & e, int n, ListNodePosi(T) p) const; //无序区间查找
   ListNodePosi(T) search(T const & e) const  //有序列表查找
      { return search(e, _size, trailer); }
   ListNodePosi(T) search(T const & e, int n, ListNodePosi(T) p) const; //有序区间查找
   ListNodePosi(T) selectMax(ListNodePosi(T) p, int 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) insertBefore(ListNodePosi(T) p, T const & e); //将e当作p的前驱插入
   ListNodePosi(T) insertAfter(ListNodePosi(T) p, T const & e); //将e当作p的后继插入
   T remove(ListNodePosi(T) p); //删除合法位置p处的节点,返回被删除节点
   void merge(List<T>& L) { merge(first(), size, L, L.first(), L._size); } //全列表归并
   void sort(ListNodePosi(T) p, int n); //列表区间排序
   void sort() { sort(first(), _size); } //列表整体排序
   int deduplicate(); //无序去重
   int uniquify(); //有序去重
   void reverse(); //前后倒置(习题)
// 遍历
   void traverse(void (*)(T&)); //遍历,依次实施visit操作(函数指针,只读或局部性修改)
   template <typename VST> //操作器
   void traverse(VST&); //遍历,依次实施visit操作(函数对象,可全局性修改)
}; //List

#include "List_implementation.h"
时间: 2024-11-08 19:40:34

List::定义的相关文章

条件、循环、函数定义、字符串操作练习

注意标准库的两种导入与使用方式,建议大家采用<库名>.<函数名>的方式. 对前面的代码进行优化,用for,while,if,def实现: 用循环画五角星 1 import turtle 2 3 turtle.fillcolor("red") 4 turtle.begin_fill() 5 for i in range(5): 6 turtle.forward(100) 7 turtle.right(144) 8 turtle.end_fill() 用循环画同心圆

C++ 枚举定义

我们在平常的编程中,时常需要为一些属性定义一组可以选择的值,比如文件打开的状态可能会有三种:输入 输出和追加 我们一般情况下记录这些状态是让每一个状态和一个常数相对应   比如 1 const int input=0; 2 const int output=1; 3 const int append=2; 这个方法虽然也是可以得,不过它有一个明显的缺点就是    没有指出这些值是相关联的 而C++中的  枚举  提供了一种替代的方法   不但可以定义常数集   还可以将其聚集成组    如下:

宏定义中的#,##,...,do{}while(0),__VA_ARGS__

宏定义中的#,## 1.在一个预处理器宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组 #define syslog(a) fprintf(stderr,"Warning: " #a"\n"); 2.简单的说,"## "是一种分隔连接方式,它的作用是先分隔,然后进行强制连接 举列 -- 试比较下述几个宏定义的区别 #define A1(name, type)  type name_##type##_type 或 #define A

如何定义一个有效的OWIN Startup Class

命名约定 Katana在程序集内的程序集名称空间下查找一个叫做Startup的类, 通过属性指定 [assembly: OwinStartup(typeof(OwinConsoleApp.Startup))] 通过配置文件 <add key="owin:appStartup" value="OwinConsoleApp.Startup1" /> 定义友好命名的Startup类 <appSettings> <add key="o

主键类型定义错了调试了半天

package com.itheima.demo1; import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table; @Entity@Table(name="u_user")public class User

静态修饰符static,类中的常量定义修饰符

static可以用来区分成员变量.方法是属于类本身还是属于类实例化后的对象.有static修饰的成员属于类本身,没有static修饰的成员属于类的实例. 静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失static是一个修饰符,用于修饰成员(成员变量和成员函数)静态成员随着类的加载而加载.静态成员优先于对象存在.静态成员被所有对象所共享静态成员多了一个中调用方式,可以被类名直接调用.静态的优缺点优点: 静态成员多了一种调用方式.可以直接被类名调用 格式 :类名.静态成员.也

栅格重分类和条件函数均可以实现对流量统计数据进行定义划分

ArcGIS水分分析工具的流向分析是基于D8单流向算法,如果分析使用的DEM存在凹陷点,就会产生汇,导致径流断流从而影响了分析结果.在前面章节<ArcGIS水文分析实战教程(2)ArcGIS水文分析工具的基本原理>中又介绍过D8算法,而<ArcGIS水文分析实战教程(4)地形预处理>章节中笔者也较少过如何创建无凹陷点得DEM数据,在使用流向分析工具之前可以先行阅读. 首先流向分析要使用填洼过的数据,确保DEM数据没有凹陷点.如果数据准备妥当,直接使用水文分析工具箱中的[流向]工具进

Android自己定义控件之轮播图控件

背景 近期要做一个轮播图的效果.网上看了几篇文章.基本上都能找到实现,效果还挺不错,可是在写的时候感觉每次都要单独去又一次在Activity里写一堆代码.于是自己封装了一下.这里仅仅是做了下封装成一个控件,不必每次反复写代码了. 效果图 实现分析 轮播图的功能就是实现左右滑动的广告.图片信息展示,那我们就用ViewPager来实现,由于考虑到用户体验,我们还须要在以下加一个指示器来标示滑动到了第几张轮播图.指示器我们能够用一个线性布局来依据要展示的轮播图设置显示的View,我们要做这种一个控件没

关于STM32 __IO 的变量定义

这个_IO 是指静态 这个 _IO 是指静态 volatile uint32_t 是指32位的无符号整形变量uint32_t 是指32位的无符号整形变量: 搞stm32这么久了,经常看到stm32里面库文件里面有用"_IO"定义的变量,查过一下当时记住了,过段时间又给忘记了.所以才特意的写一个博文来记住. volatile volatile 类型是这样的,其数据确实可能在未知的情况下发生变化.比如,硬件设备的终端更改了它,现在硬件设备往往也有自己的私有内存地址,比如显存,他们一般是通过

Bash脚本之函数定义和调用

把那些在脚本中重复出现并且没有任何改变的代码,封装起来,在适当的场景中调用执行.程序员将这种被封装起来的代码称为功能体,或者叫模块,也称为函数.这样看来是不是和循环类似,循环也是为了方便去多次执行一堆代码,而函数是将一堆代码写在一起,起一个名字,然后在需要这堆代码的时候只需要写上函数的名字即可.在shell脚本编程中,函数是由若干条shell命令组成的语句块,函数里面的内容和shell程序形式上是一致的.不同之处就是,shell代码可以直接被执行,而函数中的内容,不能独立执行,只有被调用的时候才