数据结构——单链表基本操作实现 (c++)

这篇具有很好参考价值的文章主要介绍了数据结构——单链表基本操作实现 (c++)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

单链表定义

单链表链式存储结构的特点是:用一组任意的存储单元存储线性表的数据元素(这里存储单元可以是连续的,也可以是不连续的),为了表示每个数据元素a与其直接后继数据元素之间的逻辑关系,除了存储信息本身外还要存储一个指示其直接后继的信息(地址).
这两部分信息组成数据元素a的存储映像称为结点,它包括两个域:存储信息的称为数据域,存储直接后继存储地址的域称为指针域,指针域中存储的信息称作指针.

单链表表示

可以参考下图:
c++单链表,数据结构,c++,链表

三个需要理解的概念:

头指针:头指针是指向链表中第一个结点的指针。若链表设有头结点,则头指针所指结点为线性表的头节点;若链表没设头结点,则头指针所指结点为线性表的首元结点。

头结点:头结点是在首元结点之前附设的一个结点,该头结点指针域指向首元结点。头结点的数据域可以不存储任何信息,也可存储信息,设定头结点的目的是使链表中第一个数据(首元结点)的操作与其他数据元素的操作相同,无需进行特殊处理。

首元结点:首元结点是指链表中存储第一个数据元素a的结点。如上图所示的A。

代码实现

1.单链表存储结构和初始化操作

//单链表存储结构
struct LinkedList {
	int data;	//结点数据域(以下我用int型数据类型)
	LinkedList* next;	//结点指针域
};

//初始化操作(创建头节点)
void InitList(LinkedList*& L) {	//这里的 *& 表示对指针的引用
	L = new LinkedList;	//生成一个头节点,用头指针 L 指向头节点
	L->next = NULL;		//头指针置空(目的是为了不指向什么奇奇怪怪的地方,也为了方便对单链表基本操作实现)
}

1.单链表存储结构包括两个方面:一是该存储节点的数据域,二是该存储节点的指针域(用来指向直接后继结点的).
2. 初始化的目的时为了生成一个头结点,上面代码InitList中的形参为指针的引用类型(*&)是对指针的一个引用操作。那么为什么这个地方要用引用指针?用指针不也行吗?肯定不行,这里简单表示为p1(形参) = p2(实参),若用指针作为形参接收实参,在开辟空间 L = new LinkedList; 时,实际接收这个新开辟的空间的指针是p1而不是p2,总的来说就是我们想初始化的是实参,开辟的空间要作用于实参上就必须得用指针的引用类型.

2.前插法

//前插法(在头节点后插入 n 个结点)
void CreateList_H(LinkedList*& L, int n = 1) {	
//n 表示前插的结点数量,这里默认设置为 1
	if (n < 1){	//若传入的n小于1,出现错误
		cout << "ERROR" << endl;
		exit(0);
	}
	//逆位序插入结点
	for (int i = 0; i < n; i++) {
		LinkedList* p = new LinkedList;	//创建新结点
		cin >> p->data;
		
		//具体插入操作
		p->next = L->next; 	
		L->next = p;
	}
}

下图是单链表(c、d、e)前插过程,因为每次插入都在头结点后,所以为逆位序插入,插入顺序为e、d、c.
c++单链表,数据结构,c++,链表

3.后插法

//后插法
void CreateList_R(LinkedList*& L, int n = 1) {
	LinkedList* r = L->next;	//创建指向尾部的指针
	while (r->next) {	//让尾指针指向链表尾部
		r = r->next;
	}
	if (n < 1) {	//若传入的n小于1,出现错误
		cout << "ERROR" << endl;
		exit(0);	//跳出程序
	}		
	for (int i = 0; i < n; i++) {
		LinkedList* p = new LinkedList;
		cin >> p->data;
		
		//具体插入操作
		p->next =r->next;
		r->next = p;
		r = p;
	}
}

下图是单链表(a、b、c)后插过程,实现该过程需要一个尾指针 r 来指向链表尾部.
c++单链表,数据结构,c++,链表

4.取值、查找和显示

//取值
void GetElem(LinkedList*& L, int i, int& e) {	
//在带头节点的单链表 L 中根据序号 i 获取元素的值,用 e 返回该值
	LinkedList* p = L->next;
	int j = 1;
	while (p && j < i) {	//p不为空 && j < i
		p = p->next;
		j++;
	}
	if (!p || j > i) {	//p为空 || i小于1
		cout << "ERROR" << endl;
		exit(0);	//跳出程序
	}
	e = p->data;	//该函数形参为引用类型,所以这里的 e 改变实参也会改变
}

//查找
LinkedList* LocateElem(LinkedList*& L, int e) {	
//在带头结点的单链表 L 中查找值为 e 的元素并返回该结点地址
	LinkedList* p = L;
	while (p && p->data != e) {	//p不为空 && p数据域不等于e
		p = p->next;
	}
	return p;	//返回指针p,因为该函数返回值类型为 LinkedList* 类型
}

//显示
void ShowList(LinkedList*& L) {
	LinkedList* p = L->next;
	while (p){	//p为空时循环结束
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
}

5.插入(指定插入)

//插入
void ListInsert(LinkedList*& L, int i, int e) {	
//在带头节点的单链表 L 中第 i 个位置插入值为 e 的新结点
	LinkedList* p = L;
	int j = 1;	//用j来记录指针p向后移次数
	while (p && j < i) {	//p不为空 && j记录次数小于i
		p = p->next;
		j++;
	}
	if (!p || j > i) {	//p为空 || i大于1
		cout << "ERROR" << endl;
		exit(0);	//跳出程序
	}	
	LinkedList* s = new LinkedList;
	
	//具体插入操作
	s->data = e;
	s->next = p->next;
	p->next = s;
}

可以参考下图:
c++单链表,数据结构,c++,链表

6.删除

//删除
void ListDelete(LinkedList*& L, int i) {	
//在带头节点的单链表 L 中,删除第 i 个结点
	LinkedList* p = L;
	int j = 1;	//用j来记录指针p向后移次数
	while (p->next && j < i) {	//p->next不为空 && j<i
		p = p->next;
		j++;
	}
	if (!p->next || j > i) {	//p->next为空 || i大于1
		cout << "ERROR" << endl;
		exit(0);
	}
	
	//具体删除操作
	LinkedList* q = p->next;
	p->next = q->next;
	delete q;	//释放该段结点空间
}

代码源文件

下面是上诉代码集合 和 main函数测试:

#include <iostream>
using namespace std;

//单链表存储结构
struct LinkedList {
	int data;	
	LinkedList* next;	
};

//初始化操作(创建头节点)
void InitList(LinkedList*& L) {	
	L = new LinkedList;	
	L->next = NULL;		
}

//前插法(在头节点后插入 n 个结点)
void CreateList_H(LinkedList*& L, int n = 1) {	
	if (n < 1){	
		cout << "ERROR" << endl;
		exit(0);
	}
	//逆位序插入结点
	for (int i = 0; i < n; i++) {
		LinkedList* p = new LinkedList;
		cin >> p->data;
		p->next = L->next; 
		L->next = p;
	}
}

//后插法
void CreateList_R(LinkedList*& L, int n = 1) {
	LinkedList* r = L->next;	
	while (r->next) {	
		r = r->next;
	}
	if (n < 1) {	
		cout << "ERROR" << endl;
		exit(0);	
	}		
	for (int i = 0; i < n; i++) {
		LinkedList* p = new LinkedList;
		cin >> p->data;
		p->next =r->next;
		r->next = p;
		r = p;
	}
}

//取值
void GetElem(LinkedList*& L, int i, int& e) {	
	LinkedList* p = L->next;
	int j = 1;
	while (p && j < i) {	
		p = p->next;
		j++;
	}
	if (!p || j > i) {	
		cout << "ERROR" << endl;
		exit(0);
	}
	e = p->data;	
}

//查找
LinkedList* LocateElem(LinkedList*& L, int e) {	
	LinkedList* p = L;
	while (p && p->data != e) {	
		p = p->next;
	}
	return p;	
}

//插入
void ListInsert(LinkedList*& L, int i, int e) {	
	LinkedList* p = L;
	int j = 1;
	while (p && j < i) {	
		p = p->next;
		j++;
	}
	if (!p || j > i) {
		cout << "ERROR" << endl;
		exit(0);
	}
	LinkedList* s = new LinkedList;
	s->data = e;
	s->next = p->next;
	p->next = s;
}

//删除
void ListDelete(LinkedList*& L, int i) {	
	LinkedList* p = L;
	int j = 1;
	while (p->next && j < i) {
		p = p->next;
		j++;
	}
	if (!p->next || j > i) {
		cout << "ERROR" << endl;
		exit(0);
	}
	LinkedList* q = p->next;
	p->next = q->next;
	delete q;	
}

//显示
void ShowList(LinkedList*& L) {
	LinkedList* p = L->next;
	while (p){	
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
}


int main() {
	//创建头指针
	LinkedList* L;

	//初始化(创建头节点,让头指针和头节点关联)
	InitList(L);

	cout << "前插:" << endl;
	CreateList_H(L, 2);
	ShowList(L);

	cout << "后插:" << endl;
	CreateList_R(L, 3);
	ShowList(L);
	
	cout << "插入元素:" << endl;
	ListInsert(L, 3, 9);
	ShowList(L);

	cout << "删除元素:" << endl;
	ListDelete(L, 2);
	ShowList(L);


	system("pause");
	return 0;
}

下面是运行截图:

c++单链表,数据结构,c++,链表文章来源地址https://www.toymoban.com/news/detail-768098.html

到了这里,关于数据结构——单链表基本操作实现 (c++)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】——单链表的基本操作(带头结点)

            单链表解决了顺序表需要大量连续存储单元的缺点,但单链表附加指针域, 存储密度较顺序表低(考点!!) 。由于单链表的元素离散地分布在存储空间中,所以单链表是 非随机存取 的存储结构,即不能直接找到表中某个特定的结点。当查找某个特定结点时,需要

    2024年02月05日
    浏览(38)
  • 数据结构上机练习——单链表的基本操作、头文件、类定义、main函数、多种链表算法的实现,含注释

      头文件和源文件分开有很多好处:可以提高编译速度、提高代码的可维护性、提高代码的可重用性和可扩展性,同时也可以使代码结构更清晰,方便代码的管理和维护。 LinkList.h test.cpp                  (下面所有函数都默认在类中实现)   我们以

    2024年02月07日
    浏览(44)
  • 【数据结构】单链表的基本操作 (C语言版)

    目录 一、单链表 1、单链表的定义: 2、单链表的优缺点: 二、单链表的基本操作算法(C语言) 1、宏定义 2、创建结构体 3、初始化 4、插入 4、求长度 5、清空 6、销毁  7、取值 8、查找 9、删除 10、头插法创建单链表 11、尾插法创建单链表 三、单链表的全部代码(C语言)

    2024年01月22日
    浏览(46)
  • 【数据结构】 循环单链表的基本操作 (C语言版)

    目录 一、循环单链表 1、循环单链表的定义: 2、循环单链表的优缺点: 二、循环单链表的基本操作算法(C语言)    1、宏定义  2、创建结构体 3、循环单链表的初始化  4、循环单链表的插入 5、求单链表长度 6、循环单链表的清空 7、循环单链表的销毁 8、循环单链表的取

    2024年01月22日
    浏览(47)
  • 【数据结构】队列基本操作的实现(C语言)

    🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。 🐌 个人主页:蜗牛牛啊 🔥 系列专栏:🛹数据结构、🛴C++ 📕 学习格言:博观而约取,厚积而薄发 🌹 欢迎进来的小伙伴,如果小伙伴们在学习的过程中,发现有需要纠正的地方,烦请指正,希望能够与

    2024年02月16日
    浏览(46)
  • 【Java】实现顺序表基本的操作(数据结构)

    在了解顺序表之前我们要先了解什么是线性表,线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构

    2024年02月03日
    浏览(46)
  • 数据结构:二叉树的基本操作(用递归实现)

             本文将通过完成以下内容来展示二叉树的基本操作,代码解释标注全面而且清晰,代码书写也十分规范,适合初学者进行学习,本篇文章算是本人的一些学习记录分享,希望对有需要的小伙伴提供一些帮助~ 本文的内容为: 用递归的方法实现以下算法: 1.以二叉

    2024年02月06日
    浏览(47)
  • 【数据结构】二叉树的构建与基本操作实现

    👀 樊梓慕: 个人主页   🎥 个人专栏: 《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.前序建立二叉树 2.销毁二叉树 3.统计 4.查找值为x的节点 5.前中后序遍历 6.层序遍历 7.判断二叉树是否

    2024年02月07日
    浏览(41)
  • 数据结构教程实验一顺序表基本操作的实现

    1.掌握线性表的顺序存贮结构及基本操作,深入了解顺序表的基本特性,以便在实际问题背景下灵活运用它们。 2.深入理解和灵活掌握顺序表的插入、删除等操作。 1.硬件:每个学生需配备计算机一台。 2.软件:Windows操作系统+Visual C++。     1.将建表、遍历、插入、删除分别

    2024年02月07日
    浏览(39)
  • 数据结构-树的遍历和基本操作(Java实现)

    二叉树的遍历分为以下三种:  前序遍历: 访问顺序为  根节点----左子树----右子树 中序遍历: 访问顺序为  左子树----根节点----右子树 后序遍历: 访问顺序为  左子树----右子树----根节点 接下来针对这3种遍历方式进行详细介绍: 上图前序遍历顺序为 1 2 3 4 5 6 上图中序遍历顺序

    2024年03月25日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包