C++ 数据结构应用——链表


代码已经封装成class啦,方便使用。


头文件:Linklist.h

  1. #include <iostream>
  2. /******************************************************
  3. Copyright: University of Science & Technology Beijing
  4. Author: Turing Aaron
  5. Date: 2017-05
  6. Description:
  7. ProgrammingLanguage: C++
  8. FunctionName -------- Description
  9. Createlist() 创建链表,申请链表头节点的空间,并将头节点的next指针指向NULL。
  10. ListInsert() 按给定链表位置序号找到位置并将元素插入到该序号后面。
  11. ListClear() 遍历链表,依次释放节点的内存。
  12. ListDel() 按照给定序列的值从链表中删除该结点。
  13. GetElem() 按序号查找链表中的元素,并返回该节点的指针。
  14. LocateElem() 按值查找(定位)链表中的元素,并返回该节点的指针。
  15. print() 遍历链表并打印元素的data.
  16. isEmpty() 判断链表是否为空。
  17. Adjmax() 计算相邻k个节点data值之和最大的第一节点。
  18. *******************************************************/
  19. class LinkList
  20. {
  21. public:
  22. //链表的构造函数,调用私有方法中的Creatlist(),下同,都是通过公共函数调用私有函数
  23. LinkList() { Createlist(); }
  24. int Adjmax(const int & k) {
  25. return Adjmax(head, k);
  26. }
  27. const int & GetElem(int i) {
  28. return GetElem(head, i)->data;
  29. }
  30. const int & LocateElem(const int & data) {
  31. LocateElem(head, data);
  32. }
  33. bool ListInsert(const int &i, const int & data) {
  34. return ListInsert(head, i, data);
  35. }
  36. bool ListDel(const int &i) {
  37. ListDel(head, i);
  38. }
  39. void ListClear() {
  40. ListClear(head);
  41. }
  42. void print() {
  43. print(head);
  44. }
  45. bool isEmpty() {
  46. return isEmpty(head);
  47. }
  48. private:
  49. struct LinkNode
  50. {
  51. int data;
  52. LinkNode *next;
  53. //LinkNode的初始化函数(调用new时会调用这个函数)
  54. LinkNode(const int & data, LinkNode *next = NULL)
  55. : data(data), next(next) { }
  56. };
  57. LinkNode *head;
  58. void Createlist();
  59. int Adjmax(LinkNode * & L, const int & k);
  60. void ListClear(LinkNode * & H);
  61. LinkNode * GetElem(LinkNode * H, int i) const;
  62. LinkNode * LocateElem(LinkNode *H, const int & data) const;
  63. bool ListInsert(LinkNode * & H, const int & i, const int & data) const;
  64. bool ListDel(LinkNode * & H, const int & i);
  65. void print(LinkNode * H);
  66. bool isEmpty(LinkNode * & head);
  67. };
  68. /*******************************************************
  69. Function: Adjmax().
  70. Description: 计算相邻k个节点data值之和最大的第一节点.
  71. Arguments: 链表头节点 LinkNode * & L, 链表长度 const int & k .
  72. Variables:
  73. VariableName -------- Description
  74. LinkNode* p 记录当前区间头指针
  75. LinkNode* q 记录当前区间尾指针
  76. int sum 记录当前区间内所有data之和;
  77. int maxSum 记录和最大的值;
  78. int maxNode 记录和最大的那个区间的第一个节点位置;
  79. int curNode 记录当前区间第一个节点位置。
  80. Return: 和最大的第一节点在链表中的序号
  81. *******************************************************/
  82. int LinkList::Adjmax(LinkNode * & L, const int & k) {
  83. //检测空链表
  84. if (L->next == NULL) return 0;
  85. //curNode为当前计数区间的头一个结点
  86. int sum = 0, maxSum = 0, maxNode = 1, curNode = 1;
  87. LinkNode *p = NULL, *q = NULL;
  88. p = q = L->next;
  89. //根据k的范围移动q指针,sum记录为q到p区间内的和
  90. //初始化sum,记录和为[1, k]的数据。
  91. for (int i = 1; i <= k ; i++) {
  92. sum += q->data;
  93. q = q->next;
  94. if(q==NULL){
  95. std::cout << "[-] ---------- 您输入的k值小于链表长度 ----------" << std::endl;
  96. return maxNode;
  97. }
  98. }
  99. maxSum = sum;
  100. //开始移动长度为k的区间,减去前一个元素,加上后一个元素,同时移动curNode,如果sum更大,则更新maxNode
  101. while (q) {
  102. sum -= p->data;
  103. p = p->next;
  104. curNode++;
  105. sum += q->data;
  106. q = q->next;
  107. if (sum > maxSum) {
  108. maxSum = sum;
  109. maxNode = curNode;
  110. }
  111. }
  112. return maxNode;
  113. }
  114. //创建链表,申请链表头结点的空间,并将头节点的next指针指向NULL。
  115. void LinkList::Createlist() {
  116. head = new LinkNode(0);
  117. }
  118. //遍历链表,依次释放结点的内存。
  119. void LinkList::ListClear(LinkNode * & H) {
  120. LinkNode * p;
  121. p = H;
  122. //从头结点开始循环删除
  123. while (p)
  124. {
  125. LinkNode *q;
  126. q = p->next;
  127. delete p;
  128. p = q;
  129. }
  130. }
  131. //按序号查找链表中的元素,并返回该节点的指针。
  132. LinkList::LinkNode * LinkList::GetElem(LinkNode * H, int i) const {
  133. //输入的i小于0或链表为空时返回NULL
  134. if (i < 0)
  135. return NULL;
  136. //新建指针指向表头
  137. LinkNode * P = H;
  138. //由于是从表头开始遍历,所以开始时位置为-1
  139. int j = -1;
  140. //从表头开始遍历i个节点
  141. while (P->next && j < i)
  142. {
  143. P = P->next;
  144. ++j;
  145. }
  146. //成功遍历到第i个节点,返回该元素的指针
  147. if (i == j) return P;
  148. //否则返回空指针
  149. else return NULL;
  150. }
  151. //按值查找(定位)链表中的元素,并返回该节点的指针。
  152. LinkList::LinkNode * LinkList::LocateElem(LinkNode *H, const int & data) const {
  153. //新建指针指向第一个元素
  154. LinkNode * P = H->next;
  155. //遍历链表,如果没找到data,P指针为NULL
  156. while (P && P->data != data)
  157. P = P->next;
  158. return P;
  159. }
  160. //按给定链表位置序号找到位置并将元素插入到该序号后面。
  161. bool LinkList::ListInsert(LinkNode * & H, const int & i, const int & data) const {
  162. LinkNode * p, *q;
  163. if (i == 0) p = H;
  164. else p = GetElem(H, i - 1);
  165. if (p == NULL)
  166. return false;
  167. else
  168. {
  169. //在q中存入数据,并把p指针的下一位给新节点q
  170. q = new LinkNode(data, p->next);
  171. p->next = q;
  172. return true;
  173. }
  174. }
  175. //按照给定序列的值从链表中删除该结点。
  176. bool LinkList::ListDel(LinkNode * & H, const int & i) {
  177. LinkNode *p, *q;
  178. //如果输入位置为0,则从头开始删除
  179. if (i == 0)
  180. p = H;
  181. //如果不是,则查找该元素
  182. else
  183. p = GetElem(H, i - 1);
  184. if (p&&p->next)
  185. {
  186. q = p->next;
  187. p->next = q->next;
  188. delete q;
  189. return true;
  190. }
  191. else
  192. return false;
  193. }
  194. //遍历链表并打印元素的data.
  195. void LinkList::print(LinkNode * H) {
  196. if (H == NULL)
  197. return;
  198. for (LinkNode *p = head->next; p; p = p->next) {
  199. std::cout << p->data << "\t";
  200. }
  201. std::cout << std::endl;
  202. }
  203. //判断链表是否为空。
  204. inline bool LinkList::isEmpty(LinkNode * & head) {
  205. return head == NULL ? true : false;
  206. }

主文件:list_app.cpp

  1. #include "LinkList.h"
  2. #include <string>
  3. #include <ctype.h>
  4. #include <fstream>
  5. #include <sstream>
  6. #include <limits>
  7. using namespace std;
  8. int main()
  9. {
  10. cout << "实验1:链表的应用 -- 作者:Turing Aaron" << endl;
  11. while (true)
  12. {
  13. menu:
  14. cout << "\n[+] 是否创建链表?\n"
  15. << "1) 创建链表\t2) 退出系统\t3) 从文件读入数据" << endl;
  16. //读入操作数并将第一个字符做为操作数
  17. string op_input;
  18. cin.clear();
  19. getline(cin, op_input);
  20. int op = op_input[0] - '0';
  21. //1) 创建链表
  22. if (op == 1)
  23. {
  24. //---初始化链表---
  25. cout << "[+] ---------- 正在初始化链表... ----------" << endl;
  26. LinkList *myList = new LinkList;
  27. cout << "[+] ---------- 初始化完毕,接下来请输入k值 ----------" << endl;
  28. int k = 0;
  29. while (true)
  30. {
  31. cin >> k;
  32. if (cin.good())
  33. break;
  34. else if (cin.fail())
  35. {
  36. cout << "[-] ---------- k值输入错误,请重新输入!----------" << endl;
  37. //清空输入流
  38. cin.clear();
  39. cin.ignore(numeric_limits<streamsize>::max(), '\n');
  40. }
  41. }
  42. //---数据读取---
  43. cout << "[+] ---------- 请输入数据,#结束输入 ----------" << endl;
  44. cin.clear();
  45. int data = 0, listLen = 0;
  46. while (true)
  47. {
  48. cin >> data;
  49. //如果读入的是数字,则插入链表
  50. if (cin.good())
  51. myList->ListInsert(listLen++, data);
  52. //如果输入的不是数字,输入流cin的fail会被置位,此时读入一个字符,判断是#还是非法字符。
  53. else if (cin.fail())
  54. {
  55. char c = getchar();
  56. if (c == '#')
  57. break;
  58. cin.ignore();
  59. cout << "[-] ---------- 输入的【 " << c << " 】非法,该输入跳过! ----------" << endl;
  60. //清空错误输入流
  61. cin.clear();
  62. }
  63. }
  64. //---判断链表内是否有数据---
  65. if (myList->isEmpty())
  66. {
  67. myList->ListClear();
  68. goto menu;
  69. }
  70. //---输出链表---
  71. cout << "[+] ---------- 您输入的链表为: ----------" << endl;
  72. myList->print();
  73. //---调用Adjmax()求值---
  74. cout << "[+] ---------- 开始计算相邻 [ " << k << " ] 个节点和最大的第一个节点 ----------" << endl;
  75. int maxNode = myList->Adjmax(k);
  76. if (maxNode == 0)
  77. cout << "[-] ---------- 链表为空!请检查!----------" << endl;
  78. else
  79. {
  80. cout << "[+] 相邻 " << k << " 个结点data值之和为最大的第一结点为: " << endl;
  81. cout << "[+] 序号" << maxNode << ", data值" << myList->GetElem(maxNode - 1) << endl;
  82. }
  83. cout << "[+] ---------- 计算结束 ----------" << endl;
  84. //---析构链表---
  85. myList->ListClear();
  86. //---清除输入流---
  87. cin.clear();
  88. cin.ignore(numeric_limits<streamsize>::max(), '\n');
  89. }
  90. //2) 退出系统
  91. else if (op == 2)
  92. {
  93. cout << "[+] ---------- 感谢使用,再见 ----------" << endl;
  94. exit(0);
  95. }
  96. //3) 从文件读入数据
  97. else if (op == 3)
  98. {
  99. //------从文件读入数据------
  100. string file_name;
  101. cout << "[+] ----------- 请输入要读取的文件名字 ---------" << endl;
  102. getline(cin, file_name);
  103. ifstream fin(file_name);
  104. //------打开文件失败------
  105. if (!fin)
  106. {
  107. cout << "[-] ---------- 找不到数据文件,请检查! ----------" << endl;
  108. goto menu;
  109. }
  110. //在读到文件结束以前
  111. while (fin.peek() != EOF)
  112. {
  113. int k = 0;
  114. string k_input, data_input;
  115. getline(fin, k_input);
  116. //如果k的输入非空且第一个字符为数字,则判断为k的输入有效,否则退出循环
  117. if (!k_input.empty())
  118. k = k_input[0] - '0';
  119. else
  120. break;
  121. //建立链表
  122. LinkList *myList = new LinkList;
  123. getline(fin, data_input);
  124. //将data字符串输入变为数据流,方便链表读取
  125. istringstream sin(data_input);
  126. int data = 0, listLen = 0;
  127. while (sin >> data)
  128. {
  129. myList->ListInsert(listLen++, data);
  130. }
  131. //---输出链表---
  132. cout << "[+] ---------- 您输入的链表为: ----------" << endl;
  133. myList->print();
  134. //---调用Adjmax()求值---
  135. cout << "[+] ---------- 开始计算相邻 [ " << k << " ] 个节点和最大的第一个节点 ----------" << endl;
  136. int maxNode = myList->Adjmax(k);
  137. if (maxNode == 0)
  138. cout << "[-] ---------- 链表为空!请检查! ----------" << endl;
  139. else
  140. {
  141. cout << "[+] 相邻 " << k << " 个结点data值之和为最大的第一结点为: " << endl;
  142. cout << "[+] 序号" << maxNode << ", data值" << myList->GetElem(maxNode - 1) << endl;
  143. }
  144. cout << "---------------------------------------------------------------------------------------" << endl;
  145. //---析构链表---
  146. myList->ListClear();
  147. }
  148. fin.close();
  149. }
  150. //非法参数
  151. else
  152. cout << "[-] ---------- 非法参数,请重试! ----------" << endl;
  153. }
  154. return 0;
  155. }

其他的以后有空再补充哈

[C++] 数据结构应用——链表的更多相关文章

  1. 学习javascript数据结构(二)——链表

    前言 人生总是直向前行走,从不留下什么. 原文地址:学习javascript数据结构(二)--链表 博主博客地址:Damonare的个人博客 正文 链表简介 上一篇博客-学习javascript数据结 ...

  2. linux内核数据结构之链表

    linux内核数据结构之链表 1.前言 最近写代码需用到链表结构,正好公共库有关于链表的.第一眼看时,觉得有点新鲜,和我之前见到的链表结构不一样,只有前驱和后继指针,而没有数据域.后来看代码注释发现该 ...

  3. 数据结构之链表-链表实现及常用操作(C++篇)

    数据结构之链表-链表实现及常用操作(C++篇) 0.摘要 定义 插入节点(单向链表) 删除节点(单向链表) 反向遍历链表 找出中间节点 找出倒数第k个节点 翻转链表 判断两个链表是否相交,并返回相交点 ...

  4. python实现数据结构单链表

    #python实现数据结构单链表 # -*- coding: utf-8 -*- class Node(object): """节点""" ...

  5. JAVA数据结构之链表

    JAVA数据结构之链表 什么是链表呢? 链表作为最基本的数据结构之一,定义如下: 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的. 简单来说呢,链 ...

  6. 基本数据结构:链表(list)

    copy from:http://www.cppblog.com/cxiaojia/archive/2012/07/31/185760.html 基本数据结构:链表(list) 谈到链表之前,先说一下 ...

  7. Linux C 数据结构 ->单向链表<-(~千金散尽还复来~)

    之前看到一篇单向链表的博文,代码也看着很舒服,于是乎记录下来,留给自己~,循序渐进,慢慢 延伸到真正的内核链表~(敢问路在何方?路在脚下~) 1. 简介 链表是Linux 内核中最简单,最普通的数据结 ...

  8. ytu 2231: 交集问题(线性表)(数据结构,链表练习)

    2231: 交集问题(线性表) Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 6  Solved: 3[Submit][Status][Web Boar ...

  9. C语言数据结构-单链表的实现-初始化、销毁、长度、查找、前驱、后继、插入、删除、显示操作

    1.数据结构-单链表的实现-C语言 typedef struct LNode { int data; struct LNode* next; } LNode,*LinkList; //这两者等价.Li ...

随机推荐

  1. 【洛谷P1379】八数码难题(广搜、A*)

    八数码难题 题目描述 一.广搜: 首先要考虑用什么存每一个状态 显然每个状态都用一个矩阵存是很麻烦的. 我们可以考虑将一个3*3的矩阵用一个字符串或long long 存. 每次扩展时再转化为矩阵. ...

  2. 第36章 SDIO—SD卡读写测试—零死角玩转STM32-F429系列

    第36章     SDIO—SD卡读写测试 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/f ...

  3. SpringBoot集成Quartz(解决@Autowired空指针Null问题即依赖注入的属性为null)

    使用spring-boot作为基础框架,其理念为零配置文件,所有的配置都是基于注解和暴露bean的方式. Quartz的4个核心概念: 1.Job表示一个工作,要执行的具体内容.此接口中只有一个方法v ...

  4. SQL递归查询实现组织机构树

    系统用到的组织机构树,要实现对当前节点以及其子节点的查询,数据库SQL要用到递归查询,这也是我第一次接触SQL的递归查询. 先说一下什么是递归查询,简单说来是将一个树状结构存储在一张表里,比如一个表中 ...

  5. HDU 2047 EOF牛肉串

    水到不想整理,线性DP #include <algorithm> #include <iostream> #include <cstring> #include & ...

  6. docker镜像文件导入与导出 , 支持批量

    1. 查看镜像id sudo docker images REPOSITORY TAG IMAGE ID CREATED SIZE quay.io/calico/node v1.0.1 c70511a ...

  7. linux下Tomcat配置提示权限不够解决办法

    在终端输入命令 sudo chmod -R 777 /opt/Tomcat,那么Tomcat文件夹和它下面的所有子文件夹的属性都变成了777(读/写/执行权限)

  8. RedHat6.4安装图形行化界面

    1.1    打开电源进入RedHat shell命令行界面 1.2    查看系统镜像包括的所有软件包组信息 [root@zhongyi-test ~]# yum grouplist Loaded ...

  9. Eloquent: 修改器

    感觉好长时间没写东西了,一方面主要是自己的角色发生了变化,每天要面对各种各样的事情和突发事件,不能再有一个完整的长时间让自己静下来写代码,或者写文章. 另一方面现在公司技术栈不再停留在只有 Larav ...

  10. 使用inotify-tools与rsync构建实时备份系统

    使用inotifywait监控文件变动 inotifywait是 inotify-tools 包中提供的一个工具,它使用 inotify API 来监控文件/目录中的变动情况. 在archlinux上 ...