动态单向链表的C++实现

2024-08-22 10:18
文章标签 动态 c++ 实现 链表 单向

本文主要是介绍动态单向链表的C++实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一.概念

链表是一种特殊的数组,它的每个元素称为节点,每个节点包括两个部分:

  • 数据域:存放数据,此部分与数组相同
  • 指针域:存放了下一个节点的地址(单向链表)、存放上一个和下一个节点的地址(双向链表)

其结构如下图所示


链表比数组多了指针域,因为链表结构是通过上一个节点的指针域去找下一个数据,比如有一个链表ABCD四个节点,其中A节点是链表的第一个节点,如果要访问D节点里边的数据。操作如下:

  1. 先通过A节点的指针域找到B节点
  2. 再通过B节点的指针域找到C节点
  3. 再通过C节点的指针域找到D节点
  4. 获取D节点数据域的数据

当遍历链表中的数据时,这种方法相比数组一般更加耗时,但是他的好处在于当插入和删除数据时非常方便,数组的插入和删除需要调整之后的每个数据,而链表则只需要调整结点的指针即可,如下图所示,删除同理


二.头指针和头结点

      头指针用来唯一确定单链表的身份,头指针指向链表的第一个结点,若第一个结点不存放数据,则为头结点。链表可以没有头结点,但必须有头指针,没有头指针的话链表也就不存在了。头结点的数据域可以不存放任何信息,也可以存放链表的长度等信息。

总结:

     头指针:

  • 在线性表的链式存储结构中,头指针是指链表指向第一个结点的指针,若链表有头结点,则头指针就是指向链表头结点的指针。
  • 头指针具有标识作用,常用头指针冠以链表的名字。
  • 无论链表是否为空,头指针均不为空。头指针是链表的必要元素。

头结点:

  • 头结点是为了操作的统一与方便而设立的,放在第一个元素结点之前,其数据域一般无意义(有些情况下也可存放链表的长度等等)。
  • 有了头结点后,对在第一个元素结点前插入结点和删除第一个结点,其操作与对其它结点的操作统一了。即操作任何位置时代码相同,更加方便。
  • 头结点不是链表所必需的。

三.实践

声明: LinkList.h

//
// Created by 开机烫手 on 2018/3/11.
//
#ifndef LINEARLIST_LINKLIST_H
#define LINEARLIST_LINKLIST_Hnamespace xq {typedef struct node {int data;struct node *next;} NODE;class LinkList {private:NODE* head;int len;LinkList(const LinkList&);public:LinkList();~LinkList();bool clearList();bool isEmpty();int length();void getElem(int, int *);int locateElem(int);bool insert(int, int);bool delete_(int,int*);void sort();void print();bool push_back(int);};}
#endif //LINEARLIST_LINKLIST_H

类实现:LinkList.cpp

//
// Created by 开机烫手 on 2018/3/11.
//
#include <iostream>
#include "LinkList.h"using namespace xq;
using namespace std;LinkList::LinkList() {head = new NODE;    // 创建头结点head->next = nullptr;len = 0;
}LinkList::~LinkList() {NODE *p = head->next;NODE *q;while (p) {q = p->next;delete p;p = q;}
}bool LinkList::clearList() {NODE *p = head->next;NODE *q;while (p) {q = p->next;delete p;p = q;}len = 0;head->next = nullptr;return true;
}bool LinkList::isEmpty() {return len == 0;
}int LinkList::length() {return len;
}void LinkList::getElem(int i, int *e) {if (i <= 0 || i > len || len == 0) {*e = -999;return;}int j = 1;NODE *p = head->next;while (j < i && p) {p = p->next;j++;}*e = p->data;
}int LinkList::locateElem(int e) {int i = 1;NODE *p = head->next;while (p) {if (p->data == e)return i;p = p->next;i++;}return -1;
}bool LinkList::insert(int i, int e) {if (i <= 0 || i-1 > len)return false;int j = 1;NODE *p = head;while (p && j < i) {p = p->next;j++;}NODE *s = new NODE;s->data = e;s->next = p->next;p->next = s;len++;return true;
}void LinkList::print() {if (len == 0) {cout << "list is empty!" << endl;return;}NODE *p = head->next;while (p) {cout << p->data << ' ';p = p->next;}cout << endl;
}bool LinkList::delete_(int i, int *e) {if (i <= 0 || i > len)return false;NODE *q = head;int j = 1;NODE *p = head->next;while (j < i) {q = p;p = p->next;j++;}*e = p->data;q->next = p->next;len--;delete p;return true;
}bool LinkList::push_back(int e) {NODE *p = head->next;while (p->next) {p = p->next;}NODE *s = new NODE;s->data = e;p->next = s;s->next = nullptr;len++;return true;
}void LinkList::sort() {if (len <= 1)return;int temp;NODE *p, *q;for (int i = 0; i < len - 1; i++) {p = head->next;q = head->next->next;for (int j = 0; j < len - 1 - i; j++) {if ((p->data) > (q->data)) {temp = p->data;p->data = q->data;q->data = temp;}p = p->next;q = q->next;}}
}

代码测试:main.cpp

#include <iostream>
#include "LinkList.h"using namespace std;
using namespace xq;int main() {cout << "----------List test programe!---------- " << endl;LinkList list1;cout << "is empty " << list1.isEmpty() << endl;list1.insert(1, 1);cout << "is empty " << list1.isEmpty() << endl;list1.clearList();cout << "is empty " << list1.isEmpty() << endl;list1.insert(1, 1);list1.insert(2, 2);list1.insert(3, 3);list1.insert(4, 5);list1.insert(5, 6);list1.print();list1.insert(4, 4);list1.print();int c;list1.delete_(5, &c);list1.print();int location = list1.locateElem(3);cout << "location is " << location << endl;int num2;list1.getElem(4, &num2);cout << "num2 = " << num2 << endl;list1.push_back(10);list1.push_back(5);list1.push_back(7);list1.push_back(2);list1.print();list1.sort();cout << "sort " ;list1.print();return 0;
}

程序输出为:

----------List test programe!----------
is empty 1
is empty 0
is empty 1
1 2 3 5 6
1 2 3 4 5 6
1 2 3 4 6
location is 3
num2 = 4
1 2 3 4 6 10 5 7 2
sort 1 2 2 3 4 5 6 7 10

这篇关于动态单向链表的C++实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1095990

相关文章

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

opencv图像处理之指纹验证的实现

《opencv图像处理之指纹验证的实现》本文主要介绍了opencv图像处理之指纹验证的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、简介二、具体案例实现1. 图像显示函数2. 指纹验证函数3. 主函数4、运行结果三、总结一、

Springboot处理跨域的实现方式(附Demo)

《Springboot处理跨域的实现方式(附Demo)》:本文主要介绍Springboot处理跨域的实现方式(附Demo),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录Springboot处理跨域的方式1. 基本知识2. @CrossOrigin3. 全局跨域设置4.

Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu

基于SpringBoot实现文件秒传功能

《基于SpringBoot实现文件秒传功能》在开发Web应用时,文件上传是一个常见需求,然而,当用户需要上传大文件或相同文件多次时,会造成带宽浪费和服务器存储冗余,此时可以使用文件秒传技术通过识别重复... 目录前言文件秒传原理代码实现1. 创建项目基础结构2. 创建上传存储代码3. 创建Result类4.

SpringBoot日志配置SLF4J和Logback的方法实现

《SpringBoot日志配置SLF4J和Logback的方法实现》日志记录是不可或缺的一部分,本文主要介绍了SpringBoot日志配置SLF4J和Logback的方法实现,文中通过示例代码介绍的非... 目录一、前言二、案例一:初识日志三、案例二:使用Lombok输出日志四、案例三:配置Logback一