刚刚开始学习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++]的更多相关文章

  1. 线性表之单链表C++实现

    线性表之单链表 一.头文件:LinkedList.h //单链表是用一组任意的存储单元存放线性表的元素,这组单元可以是连续的也可以是不连续的,甚至可以是零散分布在内存中的任意位置. //单链表头文件 ...

  2. [数据结构 - 第3章] 线性表之单链表(C++实现)

    一.类定义 单链表类的定义如下: #ifndef SIGNALLIST_H #define SIGNALLIST_H typedef int ElemType; /* "ElemType类型 ...

  3. 续上文----线性表之单链表(C实现)

    本文绪上文线性表之顺序表(C实现) 本文将继续使用单链表实现线性表的另外一种存储结构.这种使用链表实现的存储结构在内存中是不连续的. C实现代码如下: #include<stdio.h> ...

  4. 【Java】 大话数据结构(2) 线性表之单链表

    本文根据<大话数据结构>一书,实现了Java版的单链表. 每个结点中只包含一个指针域的链表,称为单链表. 单链表的结构如图所示: 单链表与顺序存储结构的对比: 实现程序: package ...

  5. 线性表 (单链表、循环链表-python实现)

    一.线性表 线性表的定义: 线性表是具有相同数据类型的有限数据的序列. 线性表的特点: 出了第一个元素外,每个元素有且仅有一个直接前驱,除最后一个元素外有且只有一个后继. 线性表是一种逻辑结构,表示元 ...

  6. Java数据结构-线性表之单链表LinkedList

    线性表的链式存储结构,也称之为链式表,链表:链表的存储单元能够连续也能够不连续. 链表中的节点包括数据域和指针域.数据域为存储数据元素信息的域,指针域为存储直接后继位置(一般称为指针)的域. 注意一个 ...

  7. [C++]数据结构:线性表之(单)链表

    一 (单)链表 ADT + Status InitList(LinkList &L) 初始化(单)链表 + void printList(LinkList L) 遍历(单)链表 + int L ...

  8. 数据结构(java版)学习笔记(三)——线性表之单链表

    单链表的优点: 长度不固定,可以任意增删. 单链表的缺点: 存储密度小,因为每个数据元素,都需要额外存储一个指向下一元素的指针(双链表则需要两个指针). 要访问特定元素,只能从链表头开始,遍历到该元素 ...

  9. 【线性表基础】顺序表和单链表的插入、删除等基本操作【Java版】

    本文表述了线性表及其基本操作的代码[Java实现] 参考书籍 :<数据结构 --Java语言描述>/刘小晶 ,杜选主编 线性表需要的基本功能有:动态地增长或收缩:对线性表的任何数据元素进行 ...

随机推荐

  1. leetcode -- permutation 总结

    leetcode上关于permutation有如下几题 Permutation Sequence Next Permutation Permutations Permutations II

  2. UE4读取脑电波MindWave插件(展示如何使用第三方库制作UE4插件)

    MyEEGPlugin.uplugin { , , "VersionName": "1.0", "FriendlyName": " ...

  3. C++异常 返回错误码

    一种比异常终止更灵活的方法是,使用函数的返回值来指出问题.例如,ostream类的get(void)成员ASCII码,但到达文件尾时,将返回特殊值EOF.对hmean()来说,这种方法不管用.任何树脂 ...

  4. java基础---->java中字符编码问题(一)

    这里面对java中的字符编码做一个总结,毕竟在项目中会经常遇到这个问题.爱不爱都可以,我怎样都依你,连借口我都帮你寻. 文件的编码格式 一.关于中文的二进制字节问题 public static Str ...

  5. sencha touch 入门系列 (七)sencha touch 类系统讲解(上)

    在mvc结构的基础上,sencha touch又使用了sencha公司为extjs4开发出来的类系统,在面向对象的编程语言中,类是对对象的定义,它描述了对象所包含的大量属性和方法. 跟面向对象语言类似 ...

  6. 解决在微信中部分IOS不能自动播放背景音乐

    前言在做各种HTML5场景页面的时候,插入背景音乐是一个很普遍的需求.我们都知道,IOS下的safari是无法自动播放音乐的,以至一直以来造成一种错误的认识,iso是无法自动播放媒体资源的.直到微信火 ...

  7. 转载-解决使用httpClient 4.3.x登陆 https时的证书报错问题

    今天在使用httpClient4.3.6模拟登陆https网站的时候出现了证书报错的问题,这是在开源中国社区里找到的可行的答案(原文链接:http://www.oschina.net/question ...

  8. 【BZOJ2157】旅游 树链剖分+线段树

    [BZOJ2157]旅游 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本 ...

  9. gradle多项目 svn依赖

    当svn有多个子项目且没有根项目的时候,用eclipse拷贝下来是容易出问题的,经常子项目之间的依赖会有问题,还是推荐用IDEA. 操作说明: 如果SVN有 A,B,C,D四个项目,A为web项目,B ...

  10. org.apache.log4j日志级别

    日志记录器(Logger)是日志处理的核心组件.log4j具有7种级别(Level).日志记录器(Logger)的可用级别Level (不包括自定义级别 Level)优先级从高到低:OFF.FATAL ...