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


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


头文件:Linklist.h

#include <iostream>
/******************************************************
Copyright: University of Science & Technology Beijing
Author: Turing Aaron
Date: 2017-05
Description:
ProgrammingLanguage: C++
FunctionName -------- Description
Createlist() 创建链表,申请链表头节点的空间,并将头节点的next指针指向NULL。
ListInsert() 按给定链表位置序号找到位置并将元素插入到该序号后面。
ListClear() 遍历链表,依次释放节点的内存。
ListDel() 按照给定序列的值从链表中删除该结点。
GetElem() 按序号查找链表中的元素,并返回该节点的指针。
LocateElem() 按值查找(定位)链表中的元素,并返回该节点的指针。
print() 遍历链表并打印元素的data.
isEmpty() 判断链表是否为空。
Adjmax() 计算相邻k个节点data值之和最大的第一节点。 *******************************************************/ class LinkList
{
public:
//链表的构造函数,调用私有方法中的Creatlist(),下同,都是通过公共函数调用私有函数
LinkList() { Createlist(); }
int Adjmax(const int & k) {
return Adjmax(head, k);
} const int & GetElem(int i) {
return GetElem(head, i)->data;
}
const int & LocateElem(const int & data) {
LocateElem(head, data);
}
bool ListInsert(const int &i, const int & data) {
return ListInsert(head, i, data);
}
bool ListDel(const int &i) {
ListDel(head, i);
}
void ListClear() {
ListClear(head);
}
void print() {
print(head);
}
bool isEmpty() {
return isEmpty(head);
} private:
struct LinkNode
{
int data;
LinkNode *next; //LinkNode的初始化函数(调用new时会调用这个函数)
LinkNode(const int & data, LinkNode *next = NULL)
: data(data), next(next) { }
}; LinkNode *head; void Createlist();
int Adjmax(LinkNode * & L, const int & k);
void ListClear(LinkNode * & H);
LinkNode * GetElem(LinkNode * H, int i) const;
LinkNode * LocateElem(LinkNode *H, const int & data) const;
bool ListInsert(LinkNode * & H, const int & i, const int & data) const;
bool ListDel(LinkNode * & H, const int & i);
void print(LinkNode * H);
bool isEmpty(LinkNode * & head); }; /*******************************************************
Function: Adjmax().
Description: 计算相邻k个节点data值之和最大的第一节点.
Arguments: 链表头节点 LinkNode * & L, 链表长度 const int & k .
Variables:
VariableName -------- Description
LinkNode* p 记录当前区间头指针
LinkNode* q 记录当前区间尾指针
int sum 记录当前区间内所有data之和;
int maxSum 记录和最大的值;
int maxNode 记录和最大的那个区间的第一个节点位置;
int curNode 记录当前区间第一个节点位置。 Return: 和最大的第一节点在链表中的序号
*******************************************************/
int LinkList::Adjmax(LinkNode * & L, const int & k) {
//检测空链表
if (L->next == NULL) return 0; //curNode为当前计数区间的头一个结点
int sum = 0, maxSum = 0, maxNode = 1, curNode = 1;
LinkNode *p = NULL, *q = NULL;
p = q = L->next; //根据k的范围移动q指针,sum记录为q到p区间内的和
//初始化sum,记录和为[1, k]的数据。
for (int i = 1; i <= k ; i++) {
sum += q->data;
q = q->next;
if(q==NULL){
std::cout << "[-] ---------- 您输入的k值小于链表长度 ----------" << std::endl;
return maxNode;
}
}
maxSum = sum; //开始移动长度为k的区间,减去前一个元素,加上后一个元素,同时移动curNode,如果sum更大,则更新maxNode
while (q) {
sum -= p->data;
p = p->next;
curNode++;
sum += q->data; q = q->next;
if (sum > maxSum) {
maxSum = sum;
maxNode = curNode;
}
}
return maxNode;
} //创建链表,申请链表头结点的空间,并将头节点的next指针指向NULL。
void LinkList::Createlist() {
head = new LinkNode(0);
} //遍历链表,依次释放结点的内存。
void LinkList::ListClear(LinkNode * & H) {
LinkNode * p;
p = H;
//从头结点开始循环删除
while (p)
{
LinkNode *q;
q = p->next;
delete p;
p = q;
} } //按序号查找链表中的元素,并返回该节点的指针。
LinkList::LinkNode * LinkList::GetElem(LinkNode * H, int i) const {
//输入的i小于0或链表为空时返回NULL
if (i < 0)
return NULL;
//新建指针指向表头
LinkNode * P = H;
//由于是从表头开始遍历,所以开始时位置为-1
int j = -1;
//从表头开始遍历i个节点
while (P->next && j < i)
{
P = P->next;
++j;
}
//成功遍历到第i个节点,返回该元素的指针
if (i == j) return P;
//否则返回空指针
else return NULL;
} //按值查找(定位)链表中的元素,并返回该节点的指针。
LinkList::LinkNode * LinkList::LocateElem(LinkNode *H, const int & data) const {
//新建指针指向第一个元素
LinkNode * P = H->next;
//遍历链表,如果没找到data,P指针为NULL
while (P && P->data != data)
P = P->next;
return P; } //按给定链表位置序号找到位置并将元素插入到该序号后面。
bool LinkList::ListInsert(LinkNode * & H, const int & i, const int & data) const {
LinkNode * p, *q;
if (i == 0) p = H;
else p = GetElem(H, i - 1);
if (p == NULL)
return false;
else
{
//在q中存入数据,并把p指针的下一位给新节点q
q = new LinkNode(data, p->next);
p->next = q;
return true;
}
} //按照给定序列的值从链表中删除该结点。
bool LinkList::ListDel(LinkNode * & H, const int & i) {
LinkNode *p, *q;
//如果输入位置为0,则从头开始删除
if (i == 0)
p = H;
//如果不是,则查找该元素
else
p = GetElem(H, i - 1);
if (p&&p->next)
{
q = p->next;
p->next = q->next;
delete q;
return true;
}
else
return false;
} //遍历链表并打印元素的data.
void LinkList::print(LinkNode * H) {
if (H == NULL)
return;
for (LinkNode *p = head->next; p; p = p->next) {
std::cout << p->data << "\t";
}
std::cout << std::endl;
} //判断链表是否为空。
inline bool LinkList::isEmpty(LinkNode * & head) {
return head == NULL ? true : false;
}

主文件:list_app.cpp

#include "LinkList.h"
#include <string>
#include <ctype.h>
#include <fstream>
#include <sstream>
#include <limits> using namespace std;
int main()
{ cout << "实验1:链表的应用 -- 作者:Turing Aaron" << endl;
while (true)
{
menu:
cout << "\n[+] 是否创建链表?\n"
<< "1) 创建链表\t2) 退出系统\t3) 从文件读入数据" << endl; //读入操作数并将第一个字符做为操作数
string op_input;
cin.clear();
getline(cin, op_input);
int op = op_input[0] - '0'; //1) 创建链表
if (op == 1)
{ //---初始化链表---
cout << "[+] ---------- 正在初始化链表... ----------" << endl;
LinkList *myList = new LinkList;
cout << "[+] ---------- 初始化完毕,接下来请输入k值 ----------" << endl;
int k = 0;
while (true)
{
cin >> k;
if (cin.good())
break;
else if (cin.fail())
{
cout << "[-] ---------- k值输入错误,请重新输入!----------" << endl;
//清空输入流
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
} //---数据读取---
cout << "[+] ---------- 请输入数据,#结束输入 ----------" << endl;
cin.clear();
int data = 0, listLen = 0;
while (true)
{
cin >> data; //如果读入的是数字,则插入链表
if (cin.good())
myList->ListInsert(listLen++, data); //如果输入的不是数字,输入流cin的fail会被置位,此时读入一个字符,判断是#还是非法字符。
else if (cin.fail())
{
char c = getchar();
if (c == '#')
break;
cin.ignore();
cout << "[-] ---------- 输入的【 " << c << " 】非法,该输入跳过! ----------" << endl;
//清空错误输入流
cin.clear();
}
} //---判断链表内是否有数据---
if (myList->isEmpty())
{
myList->ListClear();
goto menu;
} //---输出链表---
cout << "[+] ---------- 您输入的链表为: ----------" << endl;
myList->print(); //---调用Adjmax()求值---
cout << "[+] ---------- 开始计算相邻 [ " << k << " ] 个节点和最大的第一个节点 ----------" << endl;
int maxNode = myList->Adjmax(k);
if (maxNode == 0)
cout << "[-] ---------- 链表为空!请检查!----------" << endl;
else
{
cout << "[+] 相邻 " << k << " 个结点data值之和为最大的第一结点为: " << endl;
cout << "[+] 序号" << maxNode << ", data值" << myList->GetElem(maxNode - 1) << endl;
}
cout << "[+] ---------- 计算结束 ----------" << endl; //---析构链表---
myList->ListClear(); //---清除输入流---
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
} //2) 退出系统
else if (op == 2)
{
cout << "[+] ---------- 感谢使用,再见 ----------" << endl;
exit(0);
} //3) 从文件读入数据
else if (op == 3)
{
//------从文件读入数据------
string file_name;
cout << "[+] ----------- 请输入要读取的文件名字 ---------" << endl;
getline(cin, file_name);
ifstream fin(file_name);
//------打开文件失败------
if (!fin)
{
cout << "[-] ---------- 找不到数据文件,请检查! ----------" << endl;
goto menu;
}
//在读到文件结束以前
while (fin.peek() != EOF)
{
int k = 0;
string k_input, data_input;
getline(fin, k_input);
//如果k的输入非空且第一个字符为数字,则判断为k的输入有效,否则退出循环
if (!k_input.empty())
k = k_input[0] - '0';
else
break; //建立链表
LinkList *myList = new LinkList;
getline(fin, data_input); //将data字符串输入变为数据流,方便链表读取
istringstream sin(data_input);
int data = 0, listLen = 0;
while (sin >> data)
{
myList->ListInsert(listLen++, data);
} //---输出链表---
cout << "[+] ---------- 您输入的链表为: ----------" << endl;
myList->print(); //---调用Adjmax()求值---
cout << "[+] ---------- 开始计算相邻 [ " << k << " ] 个节点和最大的第一个节点 ----------" << endl;
int maxNode = myList->Adjmax(k);
if (maxNode == 0)
cout << "[-] ---------- 链表为空!请检查! ----------" << endl;
else
{
cout << "[+] 相邻 " << k << " 个结点data值之和为最大的第一结点为: " << endl;
cout << "[+] 序号" << maxNode << ", data值" << myList->GetElem(maxNode - 1) << endl;
}
cout << "---------------------------------------------------------------------------------------" << endl; //---析构链表---
myList->ListClear();
}
fin.close();
} //非法参数
else
cout << "[-] ---------- 非法参数,请重试! ----------" << endl;
}
return 0;
}

其他的以后有空再补充哈

[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. 2018.7.30 Oracle的Blog数据库类型读取和存

    package com.lanqiao.shopping.test; import java.io.BufferedInputStream; import java.io.BufferedOutput ...

  2. 2017.11.17 C++系列---用malloc动态给c++二维数组的申请与释放操作

    方法一:利用二级指针申请一个二维数组. #include<stdio.h> #include<stdlib.h> int main() { int **a; //用二级指针动态 ...

  3. redux详解

    redux介绍 学习文档:英文文档,中文文档,Github redux是什么 redux是一个独立专门用于做状态管理的JS库(不是react插件库),它可以用在react, angular, vue等 ...

  4. Vuex基础-Action

    在文章开始之前,再次强调一句:Vuex会把getter mutations action不管是在模块定义的还是在根级别定义的 都会注册在全局 官网API地址:https://vuex.vuejs.or ...

  5. Spring注解@Value数值取值转换字符串失败

    配置文件(yml)中,配置项如下: cebconfig: INST_CODE: 08801001 SFT_NOTIFY_CEB_CHANNEL: 123456 期望INST_CODE: 0880100 ...

  6. .NET中微软实体框架的数据访问方法

    介绍 本文的目的是解释微软的实体框架提供的三种数据访问方法.网上有好几篇关于这个话题的好文章,但是我想以一个教程的形式更详细地介绍这个话题,这个教程对于开始学习实体框架及其方法的人来说是个入门.我们将 ...

  7. 转 IOS7开发错误收集

    转自:http://blog.csdn.net/smallsky_keke/article/details/16117653 1. fatal error: file '/Applications/X ...

  8. 深入理解java虚拟机学习笔记(二)垃圾回收策略

    上篇文章介绍了JVM内存模型的相关知识,其实还有些内容可以更深入的介绍下,比如运行时常量池的动态插入,直接内存等,后期抽空再完善下上篇博客,今天来介绍下JVM中的一些垃圾回收策略.        一. ...

  9. centos 7忘记了root密码,如何改密码?

    今天服务器突然进不去了,不知道是密码被改了,还是什么情况! 服务器版本:centos 7.0 网上查找了很多文档,有些办法不可行,如果是亲自试过绝对可行的方法: 1:重启服务器,如下界面,按键盘 &q ...

  10. linux shell 部分问题解决方法

    1.  判断shell里判断字符串是否包含某个字符 a.  可以用正则式匹配符号      “=~” 举例:str="this is a string" 要想在判断str中是否含有 ...