泛型双向链表

双向链表(doublyLinkedList.h)

/*************************************************************************
> File Name : doublyLinkedList.h
> Author : Harold
> Mail : 2106562095@qq.com
> Github : www.github.com/Haroldcc
> Created Time : 2020年02月28日 10时23分06秒
************************************************************************/
/***** 双向链表 *****/ #ifndef DOUBLYLINKEDLIST_H
#define DOUBLYLINKEDLIST_H #include "linearList.h" // ADT
#include "myExceptions.h" // 异常类
#include <sstream> // for ostringstream /*** 链表节点类 ***/
template <typename T>
class Node
{
public:
T element;
Node<T> *prev;
Node<T> *next; Node(){};
Node(const T &element) { this->element = element; }
Node(const T &element, Node<T> *prev, Node<T> *next)
{
this->element = element;
this->prev = prev;
this->next = next;
}
}; /*** 双向链表类 ***/
template <typename T>
class doublyLinkedList : public linearList<T>
{
private:
void checkIndex(int index) const; // 索引异常检测 Node<T> *firstNode; // 链表头节点指针
Node<T> *lastNode; // 链表尾节点指针
int listSize; // 链表的元素个数 public:
/* 构造函数 */
doublyLinkedList(int initialCapacity = 10);
~doublyLinkedList(); /* ADT */
bool isEmpty() const { return this->listSize == 0; }
int size() const { return this->listSize; }
T &getElement(int index) const;
void setElement(int index, const T &element);
int indexOf(const T &element) const;
void removeByIndex(int index);
void removeByElement(const T &element);
void add(const T &element);
void add(int index, const T &element);
void clear();
void output(std::ostream &out) const;
}; // 默认构造
template <typename T>
doublyLinkedList<T>::doublyLinkedList(int initialCapacity)
{
if (initialCapacity < 1)
{
std::ostringstream s;
s << "初始化容量 = " << initialCapacity << "必须 > 0";
throw illegalParameterValue(s.str());
}
this->firstNode = nullptr;
this->lastNode = nullptr;
this->listSize = 0;
} // 析构函数
template <typename T>
doublyLinkedList<T>::~doublyLinkedList()
{
} template <typename T>
void doublyLinkedList<T>::checkIndex(int index) const
{
if (index < 0 || index >= this->listSize)
{
std::ostringstream s;
s << "index = " << index << "size = " << this->listSize;
throw illegalIndex(s.str());
}
} // 根据索引获取对应的节点,如未找到,抛异常
template <typename T>
T &doublyLinkedList<T>::getElement(int index) const
{
checkIndex(index); Node<T> *currentNode = this->firstNode;
for (int i = 0; i < index; i++)
currentNode = currentNode->next; return currentNode->element;
} // 根据索引设置元素值
template <typename T>
void doublyLinkedList<T>::setElement(int index, const T &element)
{
checkIndex(index); Node<T> *currentNode = this->firstNode;
for (int i = 0; i < index; i++)
currentNode = currentNode->next; currentNode->element = element;
} // 返回给定元素的索引值,若未找到返回 -1
template <typename T>
int doublyLinkedList<T>::indexOf(const T &element) const
{
Node<T> *currentNode = this->firstNode;
int index = 0;
while (currentNode != nullptr && currentNode->element != element)
{
currentNode = currentNode->next;
index++;
} if (currentNode == nullptr)
{
return -1;
}
else
{
return index;
}
} // 删除指定索引处的元素值,未找到元素抛异常
template <typename T>
void doublyLinkedList<T>::removeByIndex(int index)
{
checkIndex(index); Node<T> *deleteNode;
if (index == 0)
{ // 删除链表中的第一个元素
deleteNode = this->firstNode;
this->firstNode = this->firstNode->next;
}
else
{
Node<T> *p = this->firstNode;
for (int i = 0; i < index - 1; i++)
p = p->next; deleteNode = p->next;
p->next = p->next->next;
}
this->listSize--;
delete deleteNode;
} template <typename T>
void doublyLinkedList<T>::removeByElement(const T &element)
{
removeByIndex(indexOf(element));
} template <typename T>
void doublyLinkedList<T>::add(const T &element)
{
add(this->listSize, element);
} // 在指定索引处添加元素
template <typename T>
void doublyLinkedList<T>::add(int index, const T &element)
{
if (index < 0 || index > this->listSize)
{
std::ostringstream s;
s << "index = " << index << "size = " << this->listSize;
throw illegalIndex(s.str());
} if (index == 0)
{ // 头部插入元素
this->firstNode = new Node<T>(element, nullptr, this->firstNode);
}
else
{
Node<T> *p = this->firstNode;
for (int i = 0; i < index - 1; i++)
{
p = p->next;
}
p->next = new Node<T>(element, p->prev, p->next);
}
this->listSize++;
} template <typename T>
void doublyLinkedList<T>::clear()
{
while (this->firstNode != nullptr)
{
Node<T> *nextNode = this->firstNode->next;
delete this->firstNode;
this->firstNode = nextNode;
}
this->firstNode = this->lastNode = nullptr;
this->listSize = 0;
} template <typename T>
void doublyLinkedList<T>::output(std::ostream &out) const
{
for (Node<T> *currentNode = this->firstNode;
currentNode != nullptr;
currentNode = currentNode = currentNode->next)
out << currentNode->element << " ";
} // 重载 << 运算符
template <typename T>
std::ostream &operator<<(std::ostream &out, const doublyLinkedList<T> &list)
{
list.output(out);
return out;
} #endif

测试(testDoublyLinkedList.cpp)

/*************************************************************************
> File Name : testDoublyLinkedList.cpp
> Author : Harold
> Mail : 2106562095@qq.com
> Github : www.github.com/Haroldcc
> Created Time : 2020年02月28日 20时38分11秒
************************************************************************/
#include <iostream>
#include "linearList.h"
#include "doublyLinkedList.h" using namespace std; int main()
{
doublyLinkedList<int> list; list.add(1);
list.add(2); cout << list << endl; // test constructor
linearList<double> *x = new doublyLinkedList<double>;
doublyLinkedList<int> y, z; // test size
cout << "Initial size of x, y, and z = "
<< x->size() << ", "
<< y.size() << ", "
<< z.size() << endl; // test isEmpty
if (x->isEmpty())
cout << "x is isEmpty" << endl;
else
cout << "x is not isEmpty" << endl;
if (y.isEmpty())
cout << "y is isEmpty" << endl;
else
cout << "y is not isEmpty" << endl; // test add
y.add(0, 2);
y.add(1, 6);
y.add(0, 1);
y.add(2, 4);
y.add(3, 5);
y.add(2, 3);
cout << "Inserted 6 integers, list y should be 1 2 3 4 5 6" << endl;
cout << "Size of y = " << y.size() << endl;
if (y.isEmpty())
cout << "y is isEmpty" << endl;
else
cout << "y is not isEmpty" << endl;
y.output(cout);
cout << endl
<< "Testing overloaded <<" << endl;
cout << y << endl; // test indexOf
int index = y.indexOf(4);
if (index < 0)
cout << "4 not found" << endl;
else
cout << "The index of 4 is " << index << endl; index = y.indexOf(7);
if (index < 0)
cout << "7 not found" << endl;
else
cout << "The index of 7 is " << index << endl; // test getElement
cout << "Element with index 0 is " << y.getElement(0) << endl;
cout << "Element with index 3 is " << y.getElement(3) << endl; // test removeByIndex
y.removeByIndex(1);
cout << "Element 1 erased" << endl;
cout << "The list is " << y << endl;
y.removeByIndex(2);
cout << "Element 2 erased" << endl;
cout << "The list is " << y << endl;
y.removeByIndex(0);
cout << "Element 0 erased" << endl;
cout << "The list is " << y << endl; cout << "Size of y = " << y.size() << endl;
if (y.isEmpty())
cout << "y is isEmpty" << endl;
else
cout << "y is not isEmpty" << endl; try
{
y.add(-3, 0);
}
catch (illegalIndex e)
{
cout << "Illegal index exception" << endl;
cout << "Insert index must be between 0 and list size" << endl;
e.outputMessage();
} // a few more inserts, just for fun
y.add(0, 4);
y.add(0, 5);
y.add(0, 6);
y.add(0, 7);
cout << "y is " << y << endl; y.clear(); return 0;
}

输出

1 2
Initial size of x, y, and z = 0, 0, 0
x is isEmpty
y is isEmpty
Inserted 6 integers, list y should be 1 2 3 4 5 6
Size of y = 6
y is not isEmpty
1 2 3 4 5 6
Testing overloaded <<
1 2 3 4 5 6
The index of 4 is 3
7 not found
Element with index 0 is 1
Element with index 3 is 4
Element 1 erased
The list is 1 3 4 5 6
Element 2 erased
The list is 1 3 5 6
Element 0 erased
The list is 3 5 6
Size of y = 3
y is not isEmpty
Illegal index exception
Insert index must be between 0 and list size
index = -3size = 3
y is 7 6 5 4 3 5 6

C++泛化双向链表的更多相关文章

  1. 学习Redis你必须了解的数据结构——双向链表(JavaScript实现)

    本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文链接 http://www.cnblogs.com/tdws/ 下午分享了JavaScript实现单向链表,晚上就来补充下双向链表吧.对链表 ...

  2. 双向链表、双向循环链表的JS实现

    关于链表简介.单链表.单向循环链表.JS中的使用以及扩充方法:  单链表.循环链表的JS实现 关于四种链表的完整封装: https://github.com/zhuwq585/Data-Structu ...

  3. UML类图关系--继承(泛化)、实现、关联、聚合、组合、依赖

    在UML类图中,常见的有以下几种关系:  泛化(Generalization),  实现(Realization),关联(Association),聚合(Aggregation),组合(Composi ...

  4. 剑指Offer面试题:25.二叉搜索树与双向链表

    一.题目:二叉搜索树与双向链表 题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向.比如输入下图中左边的二叉搜索树,则输出转换之后的 ...

  5. UML类图关系(泛化 、继承、实现、依赖、关联、聚合、组合)

    UML类图关系(泛化 .继承.实现.依赖.关联.聚合.组合) 继承.实现.依赖.关联.聚合.组合的联系与区别 分别介绍这几种关系: 继承 指的是一个类(称为子类.子接口)继承另外的一个类(称为父类.父 ...

  6. Linux 内核数据结构:Linux 双向链表

    Linux 内核提供一套双向链表的实现,你可以在 include/linux/list.h 中找到.我们以双向链表着手开始介绍 Linux 内核中的数据结构 ,因为这个是在 Linux 内核中使用最为 ...

  7. Linux 内核数据结构:双向链表

    Linux 内核提供一套双向链表的实现,你可以在 include/linux/list.h 中找到.我们以双向链表着手开始介绍 Linux 内核中的数据结构 ,因为这个是在 Linux 内核中使用最为 ...

  8. [UML]UML系列——类图class的泛化关系

    系列文章       [UML]UML系列——用例图Use Case       [UML]UML系列——用例图中的各种关系(include.extend)       [UML]UML系列——类图C ...

  9. 线性表-双向链表(LinkedList)

    双向链表:如图1-3 所示,会把当前header拆分开,重新插入一个Entry<E>. LinkedList源码 0.首先这个类中的两个变量 private transient Entry ...

随机推荐

  1. winform显示word和ppt文档

    最近所做的项目中需要在Winform窗体中显示Office文档.刚开始就使用webBrowser控件实现的,但是后来发现这个控件在显示Office文档的时候有个限制:只支持Office2003之前的版 ...

  2. Apsara Clouder云计算专项技能认证:网站建设-简单动态网站搭建

    一.课程介绍 1.课程目标 了解静态网站和动态网站的区别 掌握动态网站的不同实现方式 在阿里云上如何搭建 wordPress网站以及 wordPress 网站的管理和优化 二.网站搭建的类型 1.网站 ...

  3. Tricks of Android's GUI

    Tricks of Android's GUI */--> Tricks of Android's GUI 1 layoutweight In LinearLayout, the default ...

  4. OpenCV 使用FLANN进行特征点匹配

    #include <stdio.h> #include <iostream> #include "opencv2/core/core.hpp" #inclu ...

  5. python-django项目基础-haystack&whoosh&jieba_20191124

    全文检索框架和搜索引擎的安装和配置: 安装全文检索框架,pip install django-haystack, 安装搜索引擎,pip install whoosh settings里面配置 1,注册 ...

  6. 方差分析||MSA/MSE|

    应用统计学-方差分析 数值型数据使用线性回归来研究因素对因变量的影响.类别型数据使用方差分析来研究因素对因变量的影响.方差分析是使用方差比MSA/MSE来检验均值是否全相等,即相等是H0假设,而不全相 ...

  7. OpenWrt Web 开发 LuCI框架 lua语言

    LuCI作为“FFLuCI”诞生于2008年3月份,目的是为OpenWrt固件从 Whiterussian 到 Kamikaze实现快速配置接口.Lua是一个小巧的脚本语言,很容易嵌入其它语言.轻量级 ...

  8. JAVA线程笔记。

    继承thread类 并覆写thread类中的run()方法. class 类名称 extents Thread{public void run(){}}实现Runble接口的run方法 线程的star ...

  9. java中的深拷贝

    对象拷贝有时让我们忽视其重要性,又或者因为想当然而导致若干程序问题. 浅拷贝 浅拷贝即普通拷贝,即对要拷贝的对象进行复制.例如对于Entity类: class Entity{ int a; Strin ...

  10. PHP导出excel文件的多种方式

    1.第一种实现的方法 set_time_limit(0); //逐条导出数据 ob_end_clean(); header("Content-type: application/vnd.ms ...