在链式描述中,线性表的元素在内存中的存储位置是随机的,每个元素都有一个明确的指针或链指向下一个元素的位置

chain类

在此使用单向链表实现了线性表,其中最后一个节点的指针域为NULL,即它用单向链接的一组节点实现线性表

template<class T>
class chain : public linearList<T>{
public:
chain(int initialCapacity = 10);
chain(const chain<T> &);
~chain();
bool empty() const { return listSize == 0; }
int size() const { return listSize; }
T& get(int theIndex) const;
int indexOf(const T &theElement) const;
void erase(int theIndex);
void insert(int theIndex,const T &theElement);
void output(std::ostream &out) const;
private:
void checkIndex(int theIndex) const;
chainNode<T> *firstNode;
int listSize;
};

构造函数

在构造函数中创建一个空链表,即令第一个节点指针firstNode的值为NULL

template<class T>
chain<T>::chain(int initialCapacity) {
if (initialCapacity < 1) {
ostringstream s;
s << "Initial capacity = " << initialCapacity << " Must be > 0";
throw illegalParameterValue(s.str());
}
firstNode = NULL;
listSize = 0;
}

复制构造函数要复制链表theList的每一个节点:

template<class T>
chain<T>::chain(const chain<T> &theList) {
listSize = theList.listSize;
if (listSize == 0) {
firstNode = NULL;
return;
}
chainNode<T> *sourceNode = theList.firstNode;
firstNode = new chainNode<T>(sourceNode->element);
sourceNode = sourceNode->next;
chainNode<T> *targetNode = firstNode;
while (sourceNode != NULL) {
targetNode->next = new chainNode<T>(sourceNode->element);
targetNode = targetNode->next;
sourceNode = sourceNode->next;
}
targetNode->next = NULL;
}

析构函数

析构函数要逐个清除链表的节点,实现的策略是重复清除链表的首元素节点,直到链表为空

template<class T>
chain<T>::~chain() {
while (firstNode != NULL) {
chainNode<T> *nextNode = firstNode->next;
delete firstNode;
firstNode = nextNode;
}
}

基本方法

get方法在链表中,寻找索引为theIndex的元素,必须从第一个节点开始,跟踪链域next直至找到所需的元素节点指针

template<class T>
T& chain<T>::get(int theIndex) const {
checkIndex(theIndex);
chainNode<T> *currentNode = firstNode;
for (int i = 0; i<theIndex; i++)
currentNode = currentNode->next;
return currentNode->element;
}

indexOf方法搜索链表,寻找元素

template<class T>
int chain<T>::indexOf(const T &theElement) const {
chainNode<T> *currentNode = firstNode;
int index = 0;
while (currentNode != NULL && currentNode->element != theElement) {
currentNode = currentNode->next;
index++;
}
if (currentNode == NULL) {
return -1;
}
return index;
}

erase方法删除索引为theIndex的元素,要考虑三种情况:

  1. listSize < 0 && listSize >= listSize,即listSize在无效范围
  2. 删除非空表的第0个元素节点
  3. 删除其他元素节点
template<class T>
void chain<T>::erase(int theIndex) {
checkIndex(theIndex);
chainNode<T> *deleteNode;
if (theIndex == 0) {
deleteNode = firstNode;
firstNode = firstNode->next;
} else {
chainNode<T> *p = firstNode;
for (int i = 0; i < theIndex - 1; i++)
p = p->next;
deleteNode = p->next;
p->next = p->next->next;
}
listSize--;
delete deleteNode;
}

insert方法插入和删除的过程相似,在链表中索引为theIndex的位置上插入一个新元素,要首先找到索引为theIndex-1的元素节点,然后在该节点之后插入新元素节点

template<class T>
void chain<T>::insert(int theIndex, const T &theElement) {
if (theIndex < 0 || theIndex > listSize) {
ostringstream s;
s << "index = " << theIndex << " size = " << listSize;
throw illegalIndex(s.str());
}
if (theIndex == 0) {
firstNode = new chainNode<T>(theElement,firstNode);
} else {
chainNode<T> *p = firstNode;
for (int i = 0;i < theIndex - 1; i++)
p = p->next;
p->next = new chainNode<T>(theElement,p->next);
}
listSize++;
}

output方法用于输出链表

template<class T>
void chain<T>::output(ostream &out) const {
for (chainNode<T>* currentNode = firstNode;currentNode != NULL; currentNode = currentNode->next) {
out << currentNode->element << " ";
}
} template<class T>
ostream& operator<<(ostream &out,const chain<T> &x) {
x.output(out); return out;
}

迭代器类

对于单链表,定义了一个向前迭代器

template<class T>
class iterator {
public:
iterator(chainNode<T>* theNode = NULL) { node = theNode; }
T& operator*() const { return node->element; }
T* operator->() const { return &node->element; } iterator& operator++() { node = node->next; return *this; }
iterator& operator++(int) { iterator old = *this; node = node->next; return old; }
bool operator!=(const iterator right) const { return node != right.node; }
bool operator==(const iterator right) const { return node == right.node; }
protected:
chainNode<T> *node;
};

链式描述线性表(C++实现)的更多相关文章

  1. c++实验3 链式存储线性表

    1.线性表链式存储结构及基本操作算法实现 (1)单链表存储结构类的定义: #include <iostream> using namespace std; template <cla ...

  2. java哈希表(线性探测哈希表。链式哈希表)

    哈希表(散列表) 通过哈希函数使元素的存储位置与它 的关键码之间能够建立一一映射的关系,在查找时可以很快找到该元素. 哈希表hash table(key,value) 的做法其实很简单,就是把Key通 ...

  3. 数据结构 链式哈希表(Hash Table)的接口定义与实现分析(完整代码)

    链式哈希表的接口定义 关于哈希表与链式哈希表的描述可以参阅:http://www.cnblogs.com/idreamo/p/7990860.html 链式哈希表的操作与属性有:初始化.销毁.插入元素 ...

  4. [C++]使用vector描述线性表定义及基本操作

    #ifndef VECTORLIST_H #define VECTORLIST_H #include<iostream> #include"linearlist.h" ...

  5. C 线性表的链式存储实现及插入、删除等操作示例

    一.链式存储的优势 线性表的存储可以通过顺序存储或链式存储实现,其中顺序存储基于数组实现(见本人上一篇博客),在进行插入删除等操作时,需对表内某一部分元素逐个移动,效率较低.而链式结构不依赖于地址连续 ...

  6. 队列链式存储 - 设计与实现 - API函数

    队列相关基础内容参我的博文:队列顺序存储 - 设计与实现 - API函数 队列也是一种特殊的线性表:可以用线性表链式存储来模拟队列的链式存储. 主要代码: // linkqueue.h // 队列链式 ...

  7. PHP数据结构之三 线性表中的单链表的PHP实现

    线性表的链式存储:用一组任意的存储单元存储线性表中的数据元素.用这种方法存储的线性表简称线性链表. 链式存储线性表的特点:存储链表中结点的一组任意的存储单元可以是连续的,也可以是不连续的,甚至是零散分 ...

  8. 线性表之顺序存储结构(C语言动态数组实现)

    线性表的定义:N个数据元素的有限序列 线性表从存储结构上分为:顺序存储结构(数组)和 链式存储结构(链表) 顺序存储结构:是用一段连续的内存空间存储表中的数据 L=(a1,a2,a3....an) 链 ...

  9. 数据结构与算法(C/C++版)【绪论/线性表】

    声明:数据结构与算法系列博文参考了<天勤高分笔记>.<王道复习指导>.C语言中文网.非商业用途,仅为学习笔记总结! 第一章<绪论> 一.基本概念及入门常识  /// ...

  10. 线性表接口的实现_Java

    线性表是其组成元素间具有线性关系的一种线性结构,对线性表的基本操作主要有插入.删除.查找.替换等,这些操作可以在线性表的任何位置进行.线性表可以采用顺序存储结构和链式存储结构表示. 本接口的类属于da ...

随机推荐

  1. STL二分查找算法

    二分法检索又称折半检索,二分法检索的基本思想是设字典中的元素从小到大有序地存放在数组(array)中,首先将给定值key与字典中间位置上元素的关键码(key)比较,如果相等,则检索成功:否则,若key ...

  2. idea中新建java类

    project是项目,一个大目录,里面可以放多个module project里面存放: .idea文件(project相当于workplace) module(模块) out(编译生成的.class文 ...

  3. 10.14 2020 实验 7:OpenDaylight 实验——Python 中的 REST API 调用

    一.实验目的  对 Python 调用 OpenDaylight 的 REST API 方法有初步了解.   二.实验任务  本实验需要用另一种方法完成上一个实验相同的功能,即通过 Python 程序 ...

  4. webpack 3/4踩坑,我太难了,从安装、卸载、到使用,各相应的版本号,sass-loader报错-版本的原因,webpack -v 不识别,没卸载干净

     -先说卸载: wabpack@4对应的每个插件的版本号都在最后 1 全局安装的话,npm uninstall webpack -g 有时候并不能卸载干净, 2 webpack -v 可判断是否安装成 ...

  5. beamforming源码标记

    p:各阵元的声压信号矩阵 R:接收数据的自协方差矩阵 Pcbf:交叉谱矩阵

  6. subplots函数使用说明

    1.函数的功能 创建一个画布对象和一组子图对象. 2.函数的声明 fig, axs = subplots(nrows=1, ncols=1, sharex=False, sharey=False, s ...

  7. git的回退以及合并,删除什么的

    有时候不小心合并了别的分支中的commit.我们需要回退某些提交记录.可以通过reset来操作,reset 会回退到指定commit.这种方式会删除记录,我们最好使用revert命令来操作 git r ...

  8. 算法学习01—Java底层的正整数与负整数

    算法学习01 - Java 底层的正整数与负整数 本节课学到的知识 编写一个方法,打印出 int 类型数字的二进制长什么样 为什么 int 类型的最大值是 2^32 - 1,最小值是 -2^32 负整 ...

  9. windows下 mstsc 远程Ubuntu 图形界面2

    采用 xrdp-0.9.2 + xorgxrdp-0.2.0 + xfce ,可完美实现远程,且: 1.支持中断后重新连接上一次连接. 2.支持clipbord跨平台复制. 3.xfce桌面,双机打开 ...

  10. VMware虚拟机扩容--保姆级教学

    由于项目逐步的完善,需要搭建的中间件,软件越来越多,导致以前虚拟机配置20G的内存不够用了,又不想重新创建新的虚拟机,退而求更精,选择扩容. 1.外部先进入虚拟机设置,将磁盘先扩展,具体提示如下图所示 ...