【数据结构】单链表 创建 插入 删除 查找 完整代码

news2024/10/6 12:26:59

3.1 单链表

3.1.1 定义

  • 注:

    元素离散的分布在存储空间中,所以单链表是非随机存取的存储结构。

    即不能直接找到表中某个特定的结点,需要从表头开始遍历,依次查找。

  • 定义的代码

    typedef struct LNode
    {
    	ElemType data;//每个节点存放一个数据元素
    	struct LNode* next;//指向下一个节点
    }LNode,*LinkList;
    
  • 头结点和头指针

  • 初始化

    分为带或不带头结点的初始化。

    一般用带头结点的链表,会使后续操作方便。

    • 不带头结点的初始化

      bool InitList(LinkList &L)
      {
          L=NULL;
          return ture;
      }
      
    • 带头结点的初始化

      bool InitList(LinkList& L)
      {
      	L = (LNode*)malloc(sizeof(LNode));//分配一个头节点
      	if (L == NULL)return false;//分配失败
      	L->next = NULL;
      	return true;
      }
      

3.1.2 建立

1)头插法建立单链表

在链表表头插入新结点。

  • 步骤

    1.将要插入结点的指针指向 原第一个结点;

    2.将头结点指针指向 要插入的结点。

//头插法建立单链表
LinkList List_HeadInsert(LinkList& L)
{
	LNode* s;
	int x;
	InitList(L);//初始化
	scanf_s("%d", &x);//输入结点值
	//插入表中
	while (x != 9999)//9999表示结束
	{
		//创建新结点
		s = (LNode*)malloc(sizeof(LNode));
		s->data = x;
		s->next = L->next;//新结点指针域指向原来的第一个结点
		//头结点指向新结点
		L->next = s;
		scanf_s("%d", &x);
	}
	return L;
}
2)尾插法建立单链表

在链表末尾插入新结点。

  • 步骤

    1.将尾结点的指针指向新结点;

    2.更新尾指针(新尾指针变成新结点)。

//尾插法建立链表
LinkList List_TailInsert(LinkList& L)
{
    LNode* s, * r = L;//r为表尾指针
    int x;
    scanf_s("%d", &x);//输入结点值
    //插入表中
    while (x != 9999)//9999表示结束
    {
        //创建新结点
        s = (LNode*)malloc(sizeof(LNode));
        s->data = x;
        //表尾指针指向新结点
        r->next = s;
        //更新表尾结点
        r = s;
        scanf_s("%d", &x);
    }
    r->next = NULL;//尾结点指针置空
    return L;
}

3.1.3 插入

  • 步骤

    1.查找插入位置的前驱结点;

    2.将插入结点的指针 指向 插入位置的后驱结点;

    3.将前驱结点的指针指向 插入结点。

//在表L中的第i个位置上插入指定元素e
bool ListInsert(LinkList& L, int i, ElemType e)
{
	if (i < 1)return false;
	LNode* p;//指针指向当前扫描到的节点
	int j = 0;//当前p指向的是第几个节点
	//查找第i个位置
	p = L;//L指向头节点,头节点是第0个节点
	while(p!=NULL&&j<i-1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

3.1.4 删除

  • 步骤

bool ListDelete(LinkList& L, int i, ElemType& e)
{
	if (i < 1)return false;

	LNode* p;//指针p指向当前扫描到的结点
	int j = 0;//当前p指向的是第几个结点

	//循环找到第i-1个结点
	p = L;//指向头结点
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	//i值不合法
	if (p == NULL||p->next==NULL)return false;

	LNode* q = p->next;//令q指向被删除结点
	e = q->data;//用e返回元素的值
	p->next = q->next;//将*q结点从链中断开
	free(q);//释放结点存储空间
	return true;
}

3.1.5 查找

1)按序号查找结点
//按序号查找结点
LNode* GetElem(LinkList L, int i)
{
	if (i < 1)return NULL;
	int j = 1;
	LNode* p = L->next;//第1个结点指针赋给p
	while (p != NULL && j < i)
	{
		p = p->next;
		j++;
	}
	return p;
}
2)按值查找结点
//按值查找
LNode* LocateElem(LinkList L, ElemType e)
{
	LNode* p = L->next;
	while (p != NULL && p->data != e)
	{
		p = p->next;
	}
	return p;
}

* 完整代码

#include<stdio.h>
#include <malloc.h>
#include<time.h>//用于生成随机数
#include<stdlib.h>
#define ElemType int

//---------------定义---------------
typedef struct LNode
{
	ElemType data;//每个节点存放一个数据元素
	struct LNode* next;//指向下一个节点
}LNode,*LinkList;


初始化不带头节点的单链表
//bool InitList(LinkList& L) {
//	L = NULL;
//	return true;
//}
不带会麻烦

//初始化带头节点的单链表
bool InitList(LinkList& L)
{
	L = (LNode*)malloc(sizeof(LNode));//分配一个头节点
	if (L == NULL)return false;
	L->next = NULL;
	return true;
}


//---------------建立单链表---------------

//头插法建立单链表
LinkList List_HeadInsert(LinkList& L)
{
	int m;
	printf("\n1.手动输入\n2.自动生成\n");
	scanf_s("%d", &m);

	if (m == 1)
	{
		LNode* s;
		int x;
		scanf_s("%d", &x);//输入结点值
		//插入表中
		while (x != 9999)//9999表示结束
		{
			//创建新结点
			s = (LNode*)malloc(sizeof(LNode));
			s->data = x;
			s->next = L->next;//新结点指针域指向原来的第一个结点
			//头结点指向新结点
			L->next = s;
			scanf_s("%d", &x);
		}
		return L;
	}
	else if (m == 2)
	{
		LNode* s;
		int n = 10;//结点个数
		srand(time(0));//初始化随机数种子
		while (n--)
		{
			//创建新结点
			s = (LNode*)malloc(sizeof(LNode));
			s->data = rand() % 100 + 1;//随机产生100以内的数
			s->next = L->next;
			L->next = s;
		}
	}
	else
	{
		printf("请重新输入!\n");
		List_HeadInsert(L);
	}
	
}

//尾插法建立链表
LinkList List_TailInsert(LinkList& L)
{
	int m;
	printf("\n1.手动输入\n2.自动生成\n");
	scanf_s("%d", &m);

	if (m == 1)
	{
		LNode* s, * r = L;//r为表尾指针
		int x;
		scanf_s("%d", &x);//输入结点值
		//插入表中
		while (x != 9999)//9999表示结束
		{
			//创建新结点
			s = (LNode*)malloc(sizeof(LNode));
			s->data = x;
			//表尾指针指向新结点
			r->next = s;
			//更新表尾结点
			r = s;
			scanf_s("%d", &x);
		}
		r->next = NULL;//尾结点指针置空
		return L;
	}
	else if (m == 2)
	{
		LNode* s,*r=L;
		int n = 10;//结点个数
		srand(time(0));//初始化随机数种子
		while (n--)
		{
			//创建新结点
			s = (LNode*)malloc(sizeof(LNode));
			s->data = rand() % 100 + 1;//随机产生100以内的数
			r->next = s;
			r = s;
		}
		r->next = NULL;
		return L;
	}
	else
	{
		printf("请重新输入!\n");
		List_TailInsert(L);
	}
}


//---------------插入-----------------
//在表L中的第i个位置上插入指定元素e
bool ListInsert(LinkList& L, int i, ElemType e)
{
	if (i < 1)return false;
	LNode* p;//指针指向当前扫描到的节点
	int j = 0;//当前p指向的是第几个节点
	//查找第i个位置
	p = L;//L指向头节点,头节点是第0个节点
	while(p!=NULL&&j<i-1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}


//---------------删除----------------
bool ListDelete(LinkList& L, int i, ElemType& e)
{
	if (i < 1)return false;

	LNode* p;//指针p指向当前扫描到的结点
	int j = 0;//当前p指向的是第几个结点

	//循环找到第i-1个结点
	p = L;//指向头结点
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	//i值不合法
	if (p == NULL||p->next==NULL)return false;

	LNode* q = p->next;//令q指向被删除结点
	e = q->data;//用e返回元素的值
	p->next = q->next;//将*q结点从链中断开
	free(q);//释放结点存储空间
	return true;
}


//---------------查找----------------
//按序号查找结点
LNode* GetElem(LinkList L, int i)
{
	if (i < 1)return NULL;
	int j = 1;
	LNode* p = L->next;//第1个结点指针赋给p
	while (p != NULL && j < i)
	{
		p = p->next;
		j++;
	}
	return p;
}

//按值查找
LNode* LocateElem(LinkList L, ElemType e)
{
	LNode* p = L->next;
	while (p != NULL && p->data != e)
	{
		p = p->next;
	}
	return p;
}


void List_print(LinkList& L)
{
	LinkList t = L->next;
	while (t->next != NULL)
	{
		printf("%d,", t->data);
		t = t->next;
	}
	printf("%d\n", t->data);
}

void PutMenu()
{
	printf("\n----------菜单----------\n");
	printf("1.头插法创建单链表\n2 尾插法创建单链表\n");
	printf("3.插入元素\n");
	printf("4.删除元素\n");
	printf("5.按序号查找结点\n");
	printf("6.按值查找结点\n");

	printf("请选择想执行的操作:\n");
}


int main()
{
	LinkList L1;
	InitList(L1);

	//---------------菜单---------------
	PutMenu();
	int x;
	while (~scanf_s("%d", &x))
	{
		if (x == 1)
		{
			//头插法创建单链表
			List_HeadInsert(L1);
			List_print(L1);
		}
		else if (x == 2)
		{
			//尾插法创建单链表
			List_TailInsert(L1);
			List_print(L1);
		}
		else if (x == 3)
		{
			int pos, e;
			printf("请输入要插入的位置和元素:\n");
			scanf_s("%d %d", &pos, &e);
			ListInsert(L1, pos, e);
			List_print(L1);
		}
		else if (x == 4)
		{
			int pos, e;
			printf("请输入要删除的元素位置:\n");
			scanf_s("%d", &pos);
			ListDelete(L1, pos, e);
			printf("被删元素:%d\n",e);
			List_print(L1);
		}
		else if (x == 5)
		{
			LNode* p;
			int n;
			printf("请输入需要查找的序号:\n");
			scanf_s("%d", &n);
			p = GetElem(L1, n);
			printf("查找结点的值:%d", p->data);
		}
		else if (x == 6)
		{
			LNode* p;
			int n;
			printf("请输入需要查找的结点值:\n");
			scanf_s("%d", &n);
			p =LocateElem(L1, n);
			printf("success!");
		}
		PutMenu();
	}
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/680107.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第三章 处理机调度与死锁

目录 一、调度的概念、层次 2.1 调度的基本概念 2.2 调度的三个层次 2.2.1 高级调度 2.2.2 低级调度 2.2.3 中级调度 2.2.3.1 进程的挂起态 2.2.4 三层调度的联系、对比 二、进程调度的时机、切换与过程、方式 2.1 进程调度的时机 2.2 进程调度的方式 2.2.1 非抢占…

计网复习题

一、单项选择题 OSI参考模型的物理层负责&#xff08;&#xff09;。 A&#xff0e;格式化报文 B&#xff0e;为数据选择通过网络的路由(网络层) C&#xff0e;定义连接到介质的特性 D&#xff0e;提供远程文件访问能力(应用层) 下列选项中&#xff0c;不属于网络体系结构中所…

常用git操作总结

文章目录 一、git 分支命名规范&#xff08;1&#xff09;master 主分支&#xff08;2&#xff09;develop 开发分支&#xff08;3&#xff09;feature 分支&#xff08;一般简写为feat&#xff09;&#xff08;4&#xff09;hotfix 分支&#xff08;一般简写为fix&#xff09;…

如何用canvas实现一个富文本编辑器

富文本编辑器相信大家都用过&#xff0c;相关的开源项目也很多&#xff0c;虽然具体的实现不一样&#xff0c;但是大部分都是使用DOM实现的&#xff0c;但其实还有一种实现方式&#xff0c;那就是使用HTML5的canvas&#xff0c;本文会带大家使用canvas简单实现一个类似Word的富…

分布式系统学习第四天 fastcgi学习

目录 1. Nginx作为web服务器处理请求 2. http协议复习 3. fastCGI 3.1 CGI 3.3 fastCGI和spawn-fcgi安装 3.4 nginx && fastcgi 3.5我的总结 其他知识点 1. Nginx作为web服务器处理请求 nginx不能处理动态请求 因此把请求发送给fastCGI对动态请求进行处理 静态…

区块链基础之密码学及安全技术

1.2 密码学及安全技术 1.2.1 密码学知识 1.2.1.1 Hash函数 Hash(哈希) 哈希函数是一类数学函数&#xff0c;可以在有限合理的时间内&#xff0c;将任意长度的消息压缩为 固定长度的输出值&#xff0c;并且是不可逆的。其输出值称为哈希值&#xff0c;也称为散列值。 哈希算法…

越权漏洞学习-做你做不了的事情

&#xff08;一&#xff09;、什么是越权漏洞 1、了解越权漏洞&#xff1a; 越权漏洞是指一个用户或者一个攻击者通过利用系统中某一漏洞&#xff0c;可以获得超过其正常权限的权限。也就是说&#xff0c;越权漏洞会使攻击者能够执行未经授权的操作或访问受保护的资源 简单来…

从开发人员的视角面对c盘容量紧缺的一些方案

前言 随着时代的发展&#xff0c;固态价格不断地下降&#xff0c;电脑硬盘容量水平线在不断地上升&#xff0c;近几年新出的主流笔记本自带固态容量也基本上在256G以上。所以通常不会有容量不够而带来的烦恼。个人用户往往是因为视频、游戏等文件占用了大量容量&#xff0c;针…

mmrotate调研

mmrotate调研 MMrotate是什么&#xff1f; ​ 在真实场景中&#xff0c;我们见到的图像不都是方方正正的&#xff0c;比如扫描的图书和遥感图像&#xff0c;需要检测的目标通常是有一定旋转角度的。这时候就需要用到旋转目标检测方法&#xff0c;对目标进行精确的定位&#x…

第三方库介绍——mosquitto

文章目录 概述程序&#xff08;指令&#xff09;说明安装服务端与客户端服务端指令配置配置文件&#xff1a;mosquitto.conf认证配置&#xff1a;pwfile权限配置&#xff1a;aclfile启动服务器&#xff0c;选择配置文件&#xff1a;mosquitto.conf 测试发布指令&#xff1a;订阅…

基于立创EDA的原理图设计进阶(实战开发一个小项目)

目录 学习目标 原理图设计进阶——空气质量检测仪 项目需求 1、功能性需求分析 2、非功能性需求 硬件框架图 元器件选型 MCU sensor LCD WIFI KEY PWOER 原理图设计 元件PCB封装设计-DIP&#xff0c;SOP 理论知识 直插式 贴片式 学习目标 1、熟悉电子产品设…

网络编程详细讲解

网络编程 网络通信 网络 ip 地址 1.概念&#xff1a;用于唯一标识网络中的每台计算机/主机 2.查看ip地址&#xff1a;ipconfig 3.ip地址的表示形式&#xff1a;点分十进制XX.XX.XX.XX 4.每一个十进制数的范围&#xff1a;0~255 5.ip地址的组成网络地址主机地址&#xff0…

团体程序设计天梯赛-练习集L2篇①

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的普通人。 &#x1f3c0;个人主页&#xff1a;陈童学哦CSDN &#x1f4a1;所属专栏&#xff1a;PTA &#x1f381;希望各…

Python3学习之列表

目录 1.访问列表中的值 2.更新列表 3.删除列表元素 4.Python列表脚本操作符 5.Python列表截取与拼接 6.嵌套列表 7.列表比较 8.Python列表函数&方法 序列是 Python 中最基本的数据结构。序列中的每个值都有对应的位置值&#xff0c;称之为索引&#xff0c;第一个索…

Go语言doc

1、Go语言doc go doc 命令可以打印附于 Go 语言程序实体上的文档&#xff0c;我们可以通过把程序实体的标识符作为该命令的参数来 达到查看其文档的目的。 所谓Go语言的程序实体&#xff0c;是指变量、常量、函数、结构体以及接口&#xff0c;而程序实体的标识符即是代表它们…

JDBC 和数据库连接

JDBC 和数据库连接 基本介绍 JDBC为访问不同的数据库提供了统一的接口&#xff0c;为使用者屏蔽了细节问题。Java程序员使用JDBC&#xff0c;可以连接任何提供了JDBC驱动程序的数据库系统&#xff0c;从而完成对数据库的各种操作。JDBC的基本原理图&#xff3b;重要&#xff…

CSDN 个性化推荐系统的设计和演进

个性化推荐项目 个性化推荐的设计和演进项目概览项目梳理依赖管理实现代码的重构和改进持续演化 个性化推荐的设计和演进 CSDN 的个性化推荐系统&#xff0c;是从既有的推荐项目中剥离出来的一个子项目&#xff0c;这个项目随后移交到了我们AI组。在近一年的时间内&#xff0c…

机器学习实战|第5周|第3章:无监督学习与数据预处理|3.3降维|16:00~17:55

目录 一、降维的动机 (1)数据压缩 (2)数据可视化 (3)降维的弊端 二、什么是维度的诅咒&#xff1f; 三、数据集被降维后能否逆转 四、降维的主要方法 (1)投影 (2)流形学习 五、PCA PCA可以用来给高度非线性数据集降维吗&#xff1f; 假设在一个1000维数据集上执行P…

最优化理论中的惩罚函数法:概念、推导和应用

目录 1. 引言 2. 惩罚函数法的概念 2.1 惩罚函数法的基本思想 2.2 惩罚函数的定义 2.2.1 符号性质 2.2.2 惩罚性质 2.2.3 连续性质 2.3 惩罚函数法的推导 2.4 惩罚函数法的特点 2.4.1 灵活性 2.4.2 通用性 2.4.3 近似解 2.4.4 收敛性 3. 推导过程 3.1 问题建模 …

Redis实战案例6-缓存穿透及其解决案例

1. 缓存穿透 缓存穿透是指在缓存中查找一个不存在的值&#xff0c;由于缓存一般不会存储这种无效的数据&#xff0c;所以每次查询都会落到数据库上&#xff0c;导致数据库压力增大&#xff0c;严重时可能会导致数据库宕机。 解决方案&#xff1a; 方法一&#xff1a;缓存空对象…