线性表:实现单链表和子类栈(Stack)及单向队列(Queue) [C++]
刚刚开始学习c++。之前c的内容掌握的也不多,基本只是一本概论课的程度,以前使用c的struct写过的链表、用python写过简单的数据结构,就试着把两者用c++写出来,也是对c++的class,以及继承中的public/protected/private的性质进行初步了解。第一次写头文件.h和源文件.cpp分开的c++代码。过程中参考了ProLyn和kgvito的代码,基本就是百度“单链表 c++”的前几个搜索结果。
节点listNode还是用struct来写了,因为我想节点除了构造没有什么方法需要实现,变量和构造也总是需要处于public的状态方便其他类函数调用。
栈是保持先进后出(First In Last Out, 或者FILO)的数据结构,在这里只是定义了最基本的五种方法,实现从尾部添加、从尾部弹出;队列是保持先进先出(First In First Out, FIFO)的数据结构,同样定义了最基本的方法实现从尾部添加从头部弹出。二者我都使用了private继承,因为除了重新封装list的几种方法外,多数list的方法都不需要出现在这两种数据结构中,我认为禁止public访问这些方法比较好。
- // linked_list.h
- // Base class linked list "linkList", derived "linkStack" & "linkQueue"
- typedef int DataType;
- // constructing struct "listNode"
- struct listNode
- {
- DataType nodeVal;
- listNode* nextNode;
- listNode(const DataType x); // listNode construct func
- };
- // constructing base class "linklist"
- class linkList
- {
- private: // private variables headNode & tailNode
- listNode* headNode;
- listNode* tailNode;
- // construction functions, and operator overload
- public:
- linkList();
- linkList(const linkList& lista);
- linkList& operator=(linkList& lista);
- DataType operator[](int index);
- // other functions, public
- public:
- bool isEmpty();
- void PrintList();
- void PushBack(const DataType& x);
- void PushFront(const DataType& x);
- void PopBack();
- void PopFront();
- DataType PeekBack();
- DataType PeekFront();
- void InsertNext(listNode* pos, DataType x);
- void DeleteNext(listNode* pos);
- void Delete(listNode* pos);
- void Clear();
- void Remove(DataType x);
- void RemoveAll(DataType x);
- void Sort();
- int GetLength();
- listNode* Find(DataType x);
- };
- // derived class linkStack
- class linkStack : private linkList
- {
- public:
- linkStack();
- linkStack(const linkStack& stack1);
- linkStack& operator=(linkStack& stack1);
- // the least functions needed
- public:
- bool isEmpty();
- int getSize();
- void PushBack(const DataType& x);
- void PopBack();
- DataType PeekBack();
- };
- // derived class linkQueue
- class linkQueue : private linkList
- {
- public:
- linkQueue();
- linkQueue(const linkQueue& queue1);
- linkQueue& operator=(linkQueue& queue1);
- public:
- bool isEmpty();
- int getSize();
- void PushBack(const DataType& x);
- void PopFront();
- DataType PeekFront();
- }
对struct listNode,class linkList, linkStack, linkQueue的方法的具体实现,后两者基本只是对于linkList的重新封装,为了能在private继承的子类中实现,也不得不在linkList中添加了一些没什么用处的函数。其中构造函数和赋值下标运算重载的写法都是现学的…如果现学的不到位请不吝赐教!
- #include <iostream>
- #include "linked_list.h"
- using namespace std;
- // construction func for listNode
- listNode::listNode(const DataType x)
- :nodeVal(x), nextNode(nullptr)
- {}
- // construction funcs for linkList
- linkList::linkList() // without argument
- : headNode(nullptr), tailNode(nullptr)
- {}
- linkList::linkList(const linkList& lista) // with argument
- : headNode(nullptr), tailNode(nullptr)
- {
- if (lista.headNode) {
- listNode* tmp = lista.headNode;
- while (tmp->nextNode) {
- PushBack(tmp->nodeVal);
- tmp = tmp->nextNode;
- }
- PushBack(tmp->nodeVal);
- }
- }
- // operator reload =
- linkList& linkList::operator=(linkList &lista) {
- if (this != &lista) {
- swap(headNode, lista.headNode);
- swap(tailNode, lista.tailNode);
- }
- return *this;
- }
- // operator reload [](index)
- DataType linkList::operator[](int index) {
- if (index < || headNode == nullptr) {
- cout << "Invalid index!" << endl;
- return -;
- }
- else {
- listNode* tmp = headNode;
- int i;
- while (tmp != nullptr && i < index) {
- tmp = tmp->nextNode;
- i++;
- }
- if (tmp == nullptr) {
- cout << "Invalid index!" << endl;
- return -;
- }
- else {
- return tmp->nodeVal;
- }
- }
- }
- bool linkList::isEmpty() {
- if (headNode) {
- return true;
- }
- else {
- return false;
- }
- }
- int linkList::GetLength() {
- int count = ;
- listNode* tmp = headNode;
- while (tmp) {
- count++;
- tmp = tmp->nextNode;
- }
- return count;
- }
- void linkList::PrintList() {
- listNode* tmp = headNode;
- if (tmp) {
- cout << tmp->nodeVal;
- tmp = tmp->nextNode;
- while (tmp) {
- cout << "->" << tmp->nodeVal;
- tmp = tmp->nextNode;
- }
- cout << endl;
- }
- else {
- cout << "Empty linked list!" << endl;
- }
- }
- void linkList::PushBack(const DataType& x) {
- if (headNode) {
- tailNode->nextNode = new listNode(x);
- tailNode = tailNode->nextNode;
- }
- else {
- headNode = new listNode(x);
- tailNode = headNode;
- }
- }
- void linkList::PushFront(const DataType& x) {
- if (headNode) {
- listNode* tmp = new listNode(x);
- tmp->nextNode = headNode;
- headNode = tmp;
- }
- else {
- headNode = new listNode(x);
- tailNode = headNode;
- }
- }
- void linkList::PopBack() {
- if (headNode) {
- if (headNode->nextNode) {
- listNode* tmp = headNode;
- while (tmp->nextNode != tailNode) {
- tmp = tmp->nextNode;
- }
- delete tailNode;
- tmp->nextNode = nullptr;
- tailNode = tmp;
- }
- else {
- delete headNode;
- headNode = nullptr;
- tailNode = nullptr;
- }
- }
- else {
- cout << "Empty linked list!" << endl;
- }
- }
- void linkList::PopFront() {
- if (headNode) {
- if (headNode->nextNode) {
- listNode* tmp = headNode->nextNode;
- delete headNode;
- headNode = tmp;
- }
- else {
- delete headNode;
- headNode = nullptr;
- tailNode = nullptr;
- }
- }
- else {
- cout << "Empty linked list!" << endl;
- }
- }
- DataType linkList::PeekBack() {
- if (tailNode) {
- return tailNode->nodeVal;
- }
- else {
- cout << "Empty linked list!" << endl;
- return -;
- }
- }
- DataType linkList::PeekFront() {
- if (headNode) {
- return headNode->nodeVal;
- }
- else {
- cout << "Empty linked list!" << endl;
- return -;
- }
- }
- listNode* linkList::Find(DataType x) {
- listNode* targetNode = headNode;
- while (targetNode) {
- if (targetNode->nodeVal == x) {break;}
- }
- return targetNode;
- }
- void linkList::InsertNext(listNode* pos, DataType x) {
- if (pos) {
- if (pos == tailNode) {
- listNode* tmp = new listNode(x);
- pos->nextNode = tmp;
- tailNode = tmp;
- }
- else {
- listNode* tmp = new listNode(x);
- tmp->nextNode = pos->nextNode;
- pos->nextNode = tmp;
- }
- }
- else {
- cout << "Invalid position!" << endl;
- }
- }
- void linkList::DeleteNext(listNode* pos) {
- if (pos) {
- if (pos == tailNode) {
- cout << "Invalid node!" << endl;
- }
- else {
- listNode* tmp = (pos->nextNode)->nextNode;
- delete pos->nextNode;
- pos->nextNode = tmp;
- }
- }
- else {
- cout << "Invalid node!" << endl;
- }
- }
- void linkList::Remove(DataType x) {
- if (headNode) {
- if (headNode->nextNode) {
- listNode* tmp = headNode;
- while (tmp->nextNode) {
- if ((tmp->nextNode)->nodeVal == x) {
- DeleteNext(tmp);
- break;
- }
- tmp = tmp->nextNode;
- }
- }
- else {
- if (headNode->nodeVal == x) {PopFront();}
- }
- }
- }
- void linkList::RemoveAll(DataType x) {
- if (headNode) {
- listNode* tmp = headNode;
- while (tmp->nextNode) {
- if ((tmp->nextNode)->nodeVal == x) {
- if (tmp->nextNode == tailNode){
- PopBack();
- break;
- }
- else {DeleteNext(tmp);}
- }
- tmp = tmp->nextNode;
- }
- if (tmp->nodeVal == x) {
- PopBack();
- }
- }
- }
- void linkList::Clear() {
- if (headNode) {
- listNode* prev = headNode;
- listNode* tmp;
- while (prev->nextNode) {
- tmp = prev->nextNode;
- delete prev;
- prev = tmp;
- }
- headNode = nullptr;
- tailNode = nullptr;
- }
- }
- // construction funcs for linkStack
- linkStack::linkStack() // without arguments
- :linkList()
- {}
- linkStack::linkStack(const linkStack& stack1) // with an argument
- :linkList(stack1)
- {}
- // other public funcs for linkStack
- bool linkStack::isEmpty() {
- return linkList::isEmpty();
- }
- int linkStack::getSize() {
- return linkList::GetLength();
- }
- void linkStack::PushBack(const DataType& x) {
- linkList::PushBack(x);
- }
- void linkStack::PopBack() {
- linkList::PopBack();
- }
- DataType linkStack::PeekBack() {
- return linkList::PeekBack();
- }
- // construction funcs for linkQueue
- linkQueue::linkQueue()
- :linkList()
- {}
- linkQueue::linkQueue(const linkQueue& queue1)
- :linkList(queue1)
- {}
- // other public funcs for linkQueue
- bool linkQueue::isEmpty() {
- return linkList::isEmpty();
- }
- int linkQueue::getSize() {
- return linkList::GetLength();
- }
- void linkQueue::PushBack(const DataType& x) {
- linkList::PushBack(x);
- }
- void linkQueue::PopFront() {
- linkList::PopFront();
- }
- DataType linkQueue::PeekFront() {
- return linkList::PeekFront();
- }
最后还有测试代码,和主题没什么关系,但是从以前用python学习数据结构开始我就喜好把测试代码写成假交互式,所以索性贴在这里方便取用。
- #include <iostream>
- #include "linked_list.h"
- #include <stdlib.h>
- #include <map>
- using namespace std;
- static map<string, int>stringVal {
- {"Exit", },
- {"Printlist", },
- {"Pushback", },
- {"Pushfront", },
- {"Popback", },
- {"Popfront", },
- {"Clear", },
- {"Remove", },
- {"Removeall", },
- {"Sort", },
- {"Getlength", },
- {"Index", },
- {"Peekback", },
- {"Peekfront", }
- };
- int test_list() {
- linkList list1;
- cout << ">> Linked list tesing.\n"
- ">> Enter a direction, namely Printlist, Pushback, Pushfront, Popback, Peekback, "
- "Popfront, Peekfront, Clear, Remove, Removeall, Sort, Getlength or Index,"
- "enter Exit to exit." << endl;
- string direction;
- DataType parameter;
- int param;
- while () {
- cout << ">> ";
- cout.flush();
- cin >> direction;
- switch(stringVal[direction])
- {
- case :
- return ;
- case :
- list1.PrintList();
- break;
- case :
- cin >> parameter;
- list1.PushBack(parameter);
- break;
- case :
- cin >> parameter;
- list1.PushFront(parameter);
- break;
- case :
- list1.PopBack();
- break;
- case :
- list1.PopFront();
- break;
- case :
- list1.Clear();
- break;
- case :
- cin >> parameter;
- list1.Remove(parameter);
- break;
- case :
- cin >> parameter;
- list1.RemoveAll(parameter);
- break;
- /* case 9:
- list1.Sort();
- break;*/
- case :
- param = list1.GetLength();
- cout << ">> " << param << endl;
- break;
- case :
- cin >> param;
- parameter = list1[param];
- cout << ">> " << parameter << endl;
- break;
- case :
- parameter = list1.PeekBack();
- cout << ">> " << parameter << endl;
- break;
- case :
- parameter = list1.PeekFront();
- cout << ">> " << parameter << endl;
- }
- }
- return ;
- }
- int test_stack() {
- linkStack stack1;
- cout << ">> Linked list stack tesing.\n"
- ">> Enter a direction, namely Pushback, Popback or Peekback, "
- "enter Exit to exit." << endl;
- string direction;
- DataType parameter;
- int param;
- while () {
- cout << ">> ";
- cout.flush();
- cin >> direction;
- switch(stringVal[direction])
- {
- case :
- return ;
- case :
- cin >> parameter;
- stack1.PushBack(parameter);
- break;
- case :
- stack1.PopBack();
- break;
- case :
- parameter = stack1.PeekBack();
- cout << ">> " << parameter << endl;
- break;
- }
- }
- return ;
- }
- int main() {
- test_stack();
- return ;
- }
假交互式测试代码, test(), main()
线性表:实现单链表和子类栈(Stack)及单向队列(Queue) [C++]的更多相关文章
- 线性表之单链表C++实现
线性表之单链表 一.头文件:LinkedList.h //单链表是用一组任意的存储单元存放线性表的元素,这组单元可以是连续的也可以是不连续的,甚至可以是零散分布在内存中的任意位置. //单链表头文件 ...
- [数据结构 - 第3章] 线性表之单链表(C++实现)
一.类定义 单链表类的定义如下: #ifndef SIGNALLIST_H #define SIGNALLIST_H typedef int ElemType; /* "ElemType类型 ...
- 续上文----线性表之单链表(C实现)
本文绪上文线性表之顺序表(C实现) 本文将继续使用单链表实现线性表的另外一种存储结构.这种使用链表实现的存储结构在内存中是不连续的. C实现代码如下: #include<stdio.h> ...
- 【Java】 大话数据结构(2) 线性表之单链表
本文根据<大话数据结构>一书,实现了Java版的单链表. 每个结点中只包含一个指针域的链表,称为单链表. 单链表的结构如图所示: 单链表与顺序存储结构的对比: 实现程序: package ...
- 线性表 (单链表、循环链表-python实现)
一.线性表 线性表的定义: 线性表是具有相同数据类型的有限数据的序列. 线性表的特点: 出了第一个元素外,每个元素有且仅有一个直接前驱,除最后一个元素外有且只有一个后继. 线性表是一种逻辑结构,表示元 ...
- Java数据结构-线性表之单链表LinkedList
线性表的链式存储结构,也称之为链式表,链表:链表的存储单元能够连续也能够不连续. 链表中的节点包括数据域和指针域.数据域为存储数据元素信息的域,指针域为存储直接后继位置(一般称为指针)的域. 注意一个 ...
- [C++]数据结构:线性表之(单)链表
一 (单)链表 ADT + Status InitList(LinkList &L) 初始化(单)链表 + void printList(LinkList L) 遍历(单)链表 + int L ...
- 数据结构(java版)学习笔记(三)——线性表之单链表
单链表的优点: 长度不固定,可以任意增删. 单链表的缺点: 存储密度小,因为每个数据元素,都需要额外存储一个指向下一元素的指针(双链表则需要两个指针). 要访问特定元素,只能从链表头开始,遍历到该元素 ...
- 【线性表基础】顺序表和单链表的插入、删除等基本操作【Java版】
本文表述了线性表及其基本操作的代码[Java实现] 参考书籍 :<数据结构 --Java语言描述>/刘小晶 ,杜选主编 线性表需要的基本功能有:动态地增长或收缩:对线性表的任何数据元素进行 ...
随机推荐
- Maven------电脑安装Maven
转载: http://blog.csdn.net/jiuqiyuliang/article/details/45390313 注意:修改本地仓库路径时,<localRepository>D ...
- Java精选笔记_会话技术
会话及其会话技术 会话概述 指的是一个客户端(浏览器)与Web服务器之间连续发生的一系列请求和响应过程. 会话:从浏览器开启到浏览器关闭.会话技术:用来保存在会话期间 浏览器和服务器所产生的数据. 在 ...
- 在Extjs中动态增加控件
Ext.onReady(function () { Ext.QuickTips.init(); Ext.form.Field.prototype.msgTarget = 'side'; var aut ...
- swift - 各种手势用法大全
UIGestureRecognizer有许多子类,用于监听一些常见的手势事件,这些子类主要有: 1.首先创建几个view,来用于手势的检测 let view1 = UIView() let view2 ...
- HDFS原理解析(总体架构,读写操作流程)
前言 HDFS 是一个能够面向大规模数据使用的,可进行扩展的文件存储与传递系统.是一种允许文件通过网络在多台主机上分享的文件系统,可让多机器上的多用户分享文件和 存储空间.让实际上是通过网络来访问文件 ...
- grep递归查找子目录
想要在各种文件里面找一个指定的文本,本来的方法太土了,在网上搜了一下,发现个好的方法,不过也有些问题.原文如下: 第一个,这个是看别人脚本的,配合find实现,-maxdepth指定深度,如果查找到底 ...
- docker tag 详解
docker tag 用于给镜像打标签,语法如下: docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG] ① 比如我现在有一个 centos 镜像: [ro ...
- android中必备的接口回调用法
1 ,这个方法很常见,本人觉得也很实用,分享下吧 public class DirverDistanceTool { public void getDirverDistance(LatLng star ...
- Effective C++ —— 实现(五)
条款26 : 尽可能延后变量定义式的出现时间 1. 你不只应该延后变量的定义,直到非得使用该变量的前一刻为止,甚至应该尝试延后这份定义直到能够给它初值实参为止.这样,不仅能够避免构造(和析构)非必要对 ...
- Lua脚本和C++交互(二)
上一节讲了一些基本的Lua应用,下面,我要强调一下,Lua的栈的一些概念,因为这个确实很重要,你会经常用到.熟练使用Lua,最重要的就是要时刻知道什么时候栈里面的数据是什么顺序,都是什么.如果你能熟练 ...