刚刚开始学习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访问这些方法比较好。

  1. // linked_list.h
  2. // Base class linked list "linkList", derived "linkStack" & "linkQueue"
  3. typedef int DataType;
  4.  
  5. // constructing struct "listNode"
  6. struct listNode
  7. {
  8. DataType nodeVal;
  9. listNode* nextNode;
  10. listNode(const DataType x); // listNode construct func
  11. };
  12.  
  13. // constructing base class "linklist"
  14. class linkList
  15. {
  16. private: // private variables headNode & tailNode
  17. listNode* headNode;
  18. listNode* tailNode;
  19. // construction functions, and operator overload
  20. public:
  21. linkList();
  22. linkList(const linkList& lista);
  23. linkList& operator=(linkList& lista);
  24. DataType operator[](int index);
  25. // other functions, public
  26. public:
  27. bool isEmpty();
  28. void PrintList();
  29. void PushBack(const DataType& x);
  30. void PushFront(const DataType& x);
  31. void PopBack();
  32. void PopFront();
  33. DataType PeekBack();
  34. DataType PeekFront();
  35. void InsertNext(listNode* pos, DataType x);
  36. void DeleteNext(listNode* pos);
  37. void Delete(listNode* pos);
  38. void Clear();
  39. void Remove(DataType x);
  40. void RemoveAll(DataType x);
  41. void Sort();
  42. int GetLength();
  43. listNode* Find(DataType x);
  44. };
  45.  
  46. // derived class linkStack
  47. class linkStack : private linkList
  48. {
  49. public:
  50. linkStack();
  51. linkStack(const linkStack& stack1);
  52. linkStack& operator=(linkStack& stack1);
  53. // the least functions needed
  54. public:
  55. bool isEmpty();
  56. int getSize();
  57. void PushBack(const DataType& x);
  58. void PopBack();
  59. DataType PeekBack();
  60. };
  61.  
  62. // derived class linkQueue
  63. class linkQueue : private linkList
  64. {
  65. public:
  66. linkQueue();
  67. linkQueue(const linkQueue& queue1);
  68. linkQueue& operator=(linkQueue& queue1);
  69.  
  70. public:
  71. bool isEmpty();
  72. int getSize();
  73. void PushBack(const DataType& x);
  74. void PopFront();
  75. DataType PeekFront();
  76. }

  对struct listNode,class linkList, linkStack, linkQueue的方法的具体实现,后两者基本只是对于linkList的重新封装,为了能在private继承的子类中实现,也不得不在linkList中添加了一些没什么用处的函数。其中构造函数和赋值下标运算重载的写法都是现学的…如果现学的不到位请不吝赐教!

  1. #include <iostream>
  2. #include "linked_list.h"
  3. using namespace std;
  4. // construction func for listNode
  5. listNode::listNode(const DataType x)
  6. :nodeVal(x), nextNode(nullptr)
  7. {}
  8. // construction funcs for linkList
  9. linkList::linkList() // without argument
  10. : headNode(nullptr), tailNode(nullptr)
  11. {}
  12.  
  13. linkList::linkList(const linkList& lista) // with argument
  14. : headNode(nullptr), tailNode(nullptr)
  15. {
  16. if (lista.headNode) {
  17. listNode* tmp = lista.headNode;
  18. while (tmp->nextNode) {
  19. PushBack(tmp->nodeVal);
  20. tmp = tmp->nextNode;
  21. }
  22. PushBack(tmp->nodeVal);
  23. }
  24. }
  25. // operator reload =
  26. linkList& linkList::operator=(linkList &lista) {
  27. if (this != &lista) {
  28. swap(headNode, lista.headNode);
  29. swap(tailNode, lista.tailNode);
  30. }
  31. return *this;
  32. }
  33. // operator reload [](index)
  34. DataType linkList::operator[](int index) {
  35. if (index < || headNode == nullptr) {
  36. cout << "Invalid index!" << endl;
  37. return -;
  38. }
  39. else {
  40. listNode* tmp = headNode;
  41. int i;
  42. while (tmp != nullptr && i < index) {
  43. tmp = tmp->nextNode;
  44. i++;
  45. }
  46. if (tmp == nullptr) {
  47. cout << "Invalid index!" << endl;
  48. return -;
  49. }
  50. else {
  51. return tmp->nodeVal;
  52. }
  53. }
  54. }
  55.  
  56. bool linkList::isEmpty() {
  57. if (headNode) {
  58. return true;
  59. }
  60. else {
  61. return false;
  62. }
  63. }
  64.  
  65. int linkList::GetLength() {
  66. int count = ;
  67. listNode* tmp = headNode;
  68. while (tmp) {
  69. count++;
  70. tmp = tmp->nextNode;
  71. }
  72. return count;
  73. }
  74.  
  75. void linkList::PrintList() {
  76. listNode* tmp = headNode;
  77. if (tmp) {
  78. cout << tmp->nodeVal;
  79. tmp = tmp->nextNode;
  80. while (tmp) {
  81. cout << "->" << tmp->nodeVal;
  82. tmp = tmp->nextNode;
  83. }
  84. cout << endl;
  85. }
  86. else {
  87. cout << "Empty linked list!" << endl;
  88. }
  89. }
  90.  
  91. void linkList::PushBack(const DataType& x) {
  92. if (headNode) {
  93. tailNode->nextNode = new listNode(x);
  94. tailNode = tailNode->nextNode;
  95. }
  96. else {
  97. headNode = new listNode(x);
  98. tailNode = headNode;
  99. }
  100. }
  101.  
  102. void linkList::PushFront(const DataType& x) {
  103. if (headNode) {
  104. listNode* tmp = new listNode(x);
  105. tmp->nextNode = headNode;
  106. headNode = tmp;
  107. }
  108. else {
  109. headNode = new listNode(x);
  110. tailNode = headNode;
  111. }
  112. }
  113.  
  114. void linkList::PopBack() {
  115. if (headNode) {
  116. if (headNode->nextNode) {
  117. listNode* tmp = headNode;
  118. while (tmp->nextNode != tailNode) {
  119. tmp = tmp->nextNode;
  120. }
  121. delete tailNode;
  122. tmp->nextNode = nullptr;
  123. tailNode = tmp;
  124. }
  125. else {
  126. delete headNode;
  127. headNode = nullptr;
  128. tailNode = nullptr;
  129. }
  130. }
  131. else {
  132. cout << "Empty linked list!" << endl;
  133. }
  134. }
  135.  
  136. void linkList::PopFront() {
  137. if (headNode) {
  138. if (headNode->nextNode) {
  139. listNode* tmp = headNode->nextNode;
  140. delete headNode;
  141. headNode = tmp;
  142. }
  143. else {
  144. delete headNode;
  145. headNode = nullptr;
  146. tailNode = nullptr;
  147. }
  148. }
  149. else {
  150. cout << "Empty linked list!" << endl;
  151. }
  152. }
  153.  
  154. DataType linkList::PeekBack() {
  155. if (tailNode) {
  156. return tailNode->nodeVal;
  157. }
  158. else {
  159. cout << "Empty linked list!" << endl;
  160. return -;
  161. }
  162. }
  163.  
  164. DataType linkList::PeekFront() {
  165. if (headNode) {
  166. return headNode->nodeVal;
  167. }
  168. else {
  169. cout << "Empty linked list!" << endl;
  170. return -;
  171. }
  172. }
  173.  
  174. listNode* linkList::Find(DataType x) {
  175. listNode* targetNode = headNode;
  176. while (targetNode) {
  177. if (targetNode->nodeVal == x) {break;}
  178. }
  179. return targetNode;
  180. }
  181.  
  182. void linkList::InsertNext(listNode* pos, DataType x) {
  183. if (pos) {
  184. if (pos == tailNode) {
  185. listNode* tmp = new listNode(x);
  186. pos->nextNode = tmp;
  187. tailNode = tmp;
  188. }
  189. else {
  190. listNode* tmp = new listNode(x);
  191. tmp->nextNode = pos->nextNode;
  192. pos->nextNode = tmp;
  193. }
  194. }
  195. else {
  196. cout << "Invalid position!" << endl;
  197. }
  198. }
  199.  
  200. void linkList::DeleteNext(listNode* pos) {
  201. if (pos) {
  202. if (pos == tailNode) {
  203. cout << "Invalid node!" << endl;
  204. }
  205. else {
  206. listNode* tmp = (pos->nextNode)->nextNode;
  207. delete pos->nextNode;
  208. pos->nextNode = tmp;
  209. }
  210. }
  211. else {
  212. cout << "Invalid node!" << endl;
  213. }
  214. }
  215.  
  216. void linkList::Remove(DataType x) {
  217. if (headNode) {
  218. if (headNode->nextNode) {
  219. listNode* tmp = headNode;
  220. while (tmp->nextNode) {
  221. if ((tmp->nextNode)->nodeVal == x) {
  222. DeleteNext(tmp);
  223. break;
  224. }
  225. tmp = tmp->nextNode;
  226. }
  227. }
  228. else {
  229. if (headNode->nodeVal == x) {PopFront();}
  230. }
  231. }
  232. }
  233.  
  234. void linkList::RemoveAll(DataType x) {
  235. if (headNode) {
  236. listNode* tmp = headNode;
  237. while (tmp->nextNode) {
  238. if ((tmp->nextNode)->nodeVal == x) {
  239. if (tmp->nextNode == tailNode){
  240. PopBack();
  241. break;
  242. }
  243. else {DeleteNext(tmp);}
  244. }
  245. tmp = tmp->nextNode;
  246. }
  247. if (tmp->nodeVal == x) {
  248. PopBack();
  249. }
  250. }
  251. }
  252.  
  253. void linkList::Clear() {
  254. if (headNode) {
  255. listNode* prev = headNode;
  256. listNode* tmp;
  257. while (prev->nextNode) {
  258. tmp = prev->nextNode;
  259. delete prev;
  260. prev = tmp;
  261. }
  262. headNode = nullptr;
  263. tailNode = nullptr;
  264. }
  265. }
  266. // construction funcs for linkStack
  267. linkStack::linkStack() // without arguments
  268. :linkList()
  269. {}
  270.  
  271. linkStack::linkStack(const linkStack& stack1) // with an argument
  272. :linkList(stack1)
  273. {}
  274. // other public funcs for linkStack
  275. bool linkStack::isEmpty() {
  276. return linkList::isEmpty();
  277. }
  278.  
  279. int linkStack::getSize() {
  280. return linkList::GetLength();
  281. }
  282.  
  283. void linkStack::PushBack(const DataType& x) {
  284. linkList::PushBack(x);
  285. }
  286.  
  287. void linkStack::PopBack() {
  288. linkList::PopBack();
  289. }
  290.  
  291. DataType linkStack::PeekBack() {
  292. return linkList::PeekBack();
  293. }
  294. // construction funcs for linkQueue
  295. linkQueue::linkQueue()
  296. :linkList()
  297. {}
  298.  
  299. linkQueue::linkQueue(const linkQueue& queue1)
  300. :linkList(queue1)
  301. {}
  302. // other public funcs for linkQueue
  303. bool linkQueue::isEmpty() {
  304. return linkList::isEmpty();
  305. }
  306.  
  307. int linkQueue::getSize() {
  308. return linkList::GetLength();
  309. }
  310.  
  311. void linkQueue::PushBack(const DataType& x) {
  312. linkList::PushBack(x);
  313. }
  314.  
  315. void linkQueue::PopFront() {
  316. linkList::PopFront();
  317. }
  318.  
  319. DataType linkQueue::PeekFront() {
  320. return linkList::PeekFront();
  321. }

  最后还有测试代码,和主题没什么关系,但是从以前用python学习数据结构开始我就喜好把测试代码写成假交互式,所以索性贴在这里方便取用。

  1. #include <iostream>
  2. #include "linked_list.h"
  3. #include <stdlib.h>
  4. #include <map>
  5.  
  6. using namespace std;
  7.  
  8. static map<string, int>stringVal {
  9. {"Exit", },
  10. {"Printlist", },
  11. {"Pushback", },
  12. {"Pushfront", },
  13. {"Popback", },
  14. {"Popfront", },
  15. {"Clear", },
  16. {"Remove", },
  17. {"Removeall", },
  18. {"Sort", },
  19. {"Getlength", },
  20. {"Index", },
  21. {"Peekback", },
  22. {"Peekfront", }
  23. };
  24.  
  25. int test_list() {
  26. linkList list1;
  27. cout << ">> Linked list tesing.\n"
  28. ">> Enter a direction, namely Printlist, Pushback, Pushfront, Popback, Peekback, "
  29. "Popfront, Peekfront, Clear, Remove, Removeall, Sort, Getlength or Index,"
  30. "enter Exit to exit." << endl;
  31. string direction;
  32. DataType parameter;
  33. int param;
  34. while () {
  35. cout << ">> ";
  36. cout.flush();
  37. cin >> direction;
  38. switch(stringVal[direction])
  39. {
  40. case :
  41. return ;
  42. case :
  43. list1.PrintList();
  44. break;
  45. case :
  46. cin >> parameter;
  47. list1.PushBack(parameter);
  48. break;
  49. case :
  50. cin >> parameter;
  51. list1.PushFront(parameter);
  52. break;
  53. case :
  54. list1.PopBack();
  55. break;
  56. case :
  57. list1.PopFront();
  58. break;
  59. case :
  60. list1.Clear();
  61. break;
  62. case :
  63. cin >> parameter;
  64. list1.Remove(parameter);
  65. break;
  66. case :
  67. cin >> parameter;
  68. list1.RemoveAll(parameter);
  69. break;
  70. /* case 9:
  71. list1.Sort();
  72. break;*/
  73. case :
  74. param = list1.GetLength();
  75. cout << ">> " << param << endl;
  76. break;
  77. case :
  78. cin >> param;
  79. parameter = list1[param];
  80. cout << ">> " << parameter << endl;
  81. break;
  82. case :
  83. parameter = list1.PeekBack();
  84. cout << ">> " << parameter << endl;
  85. break;
  86. case :
  87. parameter = list1.PeekFront();
  88. cout << ">> " << parameter << endl;
  89. }
  90. }
  91. return ;
  92. }
  93.  
  94. int test_stack() {
  95. linkStack stack1;
  96. cout << ">> Linked list stack tesing.\n"
  97. ">> Enter a direction, namely Pushback, Popback or Peekback, "
  98. "enter Exit to exit." << endl;
  99. string direction;
  100. DataType parameter;
  101. int param;
  102. while () {
  103. cout << ">> ";
  104. cout.flush();
  105. cin >> direction;
  106. switch(stringVal[direction])
  107. {
  108. case :
  109. return ;
  110. case :
  111. cin >> parameter;
  112. stack1.PushBack(parameter);
  113. break;
  114. case :
  115. stack1.PopBack();
  116. break;
  117. case :
  118. parameter = stack1.PeekBack();
  119. cout << ">> " << parameter << endl;
  120. break;
  121. }
  122. }
  123. return ;
  124. }
  125.  
  126. int main() {
  127. test_stack();
  128. return ;
  129. }

假交互式测试代码, 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. Maven------电脑安装Maven

    转载: http://blog.csdn.net/jiuqiyuliang/article/details/45390313 注意:修改本地仓库路径时,<localRepository>D ...

  2. Java精选笔记_会话技术

    会话及其会话技术 会话概述 指的是一个客户端(浏览器)与Web服务器之间连续发生的一系列请求和响应过程. 会话:从浏览器开启到浏览器关闭.会话技术:用来保存在会话期间 浏览器和服务器所产生的数据. 在 ...

  3. 在Extjs中动态增加控件

    Ext.onReady(function () { Ext.QuickTips.init(); Ext.form.Field.prototype.msgTarget = 'side'; var aut ...

  4. swift - 各种手势用法大全

    UIGestureRecognizer有许多子类,用于监听一些常见的手势事件,这些子类主要有: 1.首先创建几个view,来用于手势的检测 let view1 = UIView() let view2 ...

  5. HDFS原理解析(总体架构,读写操作流程)

    前言 HDFS 是一个能够面向大规模数据使用的,可进行扩展的文件存储与传递系统.是一种允许文件通过网络在多台主机上分享的文件系统,可让多机器上的多用户分享文件和 存储空间.让实际上是通过网络来访问文件 ...

  6. grep递归查找子目录

    想要在各种文件里面找一个指定的文本,本来的方法太土了,在网上搜了一下,发现个好的方法,不过也有些问题.原文如下: 第一个,这个是看别人脚本的,配合find实现,-maxdepth指定深度,如果查找到底 ...

  7. docker tag 详解

    docker tag 用于给镜像打标签,语法如下: docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG] ① 比如我现在有一个 centos 镜像: [ro ...

  8. android中必备的接口回调用法

    1 ,这个方法很常见,本人觉得也很实用,分享下吧 public class DirverDistanceTool { public void getDirverDistance(LatLng star ...

  9. Effective C++ —— 实现(五)

    条款26 : 尽可能延后变量定义式的出现时间 1. 你不只应该延后变量的定义,直到非得使用该变量的前一刻为止,甚至应该尝试延后这份定义直到能够给它初值实参为止.这样,不仅能够避免构造(和析构)非必要对 ...

  10. Lua脚本和C++交互(二)

    上一节讲了一些基本的Lua应用,下面,我要强调一下,Lua的栈的一些概念,因为这个确实很重要,你会经常用到.熟练使用Lua,最重要的就是要时刻知道什么时候栈里面的数据是什么顺序,都是什么.如果你能熟练 ...