数据结构双向链表,实现增删改查

一、双向链表的描述

        在单链表中,查找直接后继结点的执行时间为O(1),而查找直接前驱的执行时间为O(n)。为克服单链表这种单向性的缺点,可以用双向链表

        在双向链表的结点中有两个指针域,一个指向直接后继,另一个指向直接前驱。

二、双向链表的存储结构

typedef char ElemType[20];  //重定义数据域的数据类型
typedef struct LNode  //定义双向链表存储结构
{
	ElemType data;
	struct LNode *next;
	struct LNode *prev;
}*DoubleLink;

三、双向链表的操作

2.1 双向链表结点创建

DoubleLink Request_space()  //在堆区申请一个结点空间
{
	DoubleLink node=(DoubleLink)malloc(sizeof(struct LNode));
	if(NULL==node)
		return NULL;
	strcpy(node->data,"");
	node->next=node->prev=NULL;
	return node;
}

2.2 双向链表遍历

int Output(DoubleLink L_list)  //实现输出
{
	if(NULL==L_list)
		return -1;
	DoubleLink p=L_list;
	do
	{
		printf("%s ",p->data);
		p=p->next;
	}while(p!=NULL);
	puts("");
	return 0;
}

2.3 双向链表头插

DoubleLink insert_head(DoubleLink L_list,ElemType value)  //实现头插
{
	DoubleLink node=Request_space();
	if(NULL==node)
		return L_list;  
	strcpy(node->data,value);
	if(NULL!=L_list)
	{
		node->next=L_list;
		L_list->prev=node;
	}
	L_list=node;
	return L_list;
}

2.4 双向链表尾插

DoubleLink insert_rear(DoubleLink L_list,ElemType value)  //实现尾插
{
	DoubleLink node=Request_space();
	strcpy(node->data,value);
	if(NULL==L_list)
		L_list=node;
	else
	{
		DoubleLink rear=L_list;
		while(rear->next!=NULL)
			rear=rear->next;
		rear->next=node;
		node->prev=rear;
	}
	return L_list;
}

2.5 双向链表头删

DoubleLink delete_head(DoubleLink L_list)  //实现头删
{
	if(NULL==L_list)
		return NULL;
	if(L_list->next==NULL)
	{
		free(L_list);
		L_list=NULL;
	}
	else
	{
		DoubleLink p=L_list->next;
		strcpy(L_list->data,p->data);
		L_list->next=p->next;
		if(p->next!=NULL)
			p->next->prev=L_list;
		free(p);
		p=NULL;
	}
	return L_list;
}

2.6 双向链表尾删

DoubleLink delete_rear(DoubleLink L_list)  //实现尾删
{
	if(NULL==L_list)
		return NULL;
	if(L_list->next==NULL)
	{
		free(L_list);
		L_list=NULL;
	}
	else
	{
		DoubleLink rear=L_list;
		while(rear->next!=NULL)
			rear=rear->next;
		rear->prev->next=NULL;
		free(rear);
		rear=NULL;
	}
	return L_list;
}

2.7 计算双向链表长度

int len_Llist(DoubleLink L_list)  //计算双向链表长度
{
	int count=0;
	if(NULL==L_list)
		return -1;
	while(L_list!=NULL)
	{
		count++;
		L_list=L_list->next;
	}
	return count;
}

2.8 双向链表逆置

DoubleLink rev_list(DoubleLink L_list)  //双向链表逆置
{
	if(NULL==L_list||L_list->next==NULL)
		return L_list;
	int len=len_Llist(L_list)-1;
	DoubleLink p=L_list->next;
	L_list->next=NULL;
    L_list->prev=L_list->next;
	for(int i=0;i<len;i++)
	{
		DoubleLink q=p;
		p=p->next;
		q->prev=q->next;
		q->next=L_list;
		L_list=q;
	}
	return L_list;
}

四、多文件编辑实现双向链表操作

头文件 head.h

#ifndef __HEAD_H__
#define __HEAD_H__

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef char ElemType[20];  //重定义数据域的数据类型
typedef struct LNode  //定义双向链表存储结构
{
	ElemType data;
	struct LNode *next;
	struct LNode *prev;
}*DoubleLink;

DoubleLink Request_space();  //在堆区申请一个结点空间
int Output(DoubleLink L_list);  //实现输出
DoubleLink insert_head(DoubleLink L_list,ElemType value);  //实现头插
DoubleLink insert_rear(DoubleLink L_list,ElemType value);  //实现尾插
DoubleLink delete_head(DoubleLink L_list);  //实现头删
DoubleLink delete_rear(DoubleLink L_list);  //实现尾删
DoubleLink rev_list(DoubleLink L_list);  //双向链表逆置

#endif

自定义函数 fun.c

#include "head.h"
DoubleLink Request_space()  //在堆区申请一个结点空间
{
	DoubleLink node=(DoubleLink)malloc(sizeof(struct LNode));
	if(NULL==node)
		return NULL;
	strcpy(node->data,"");
	node->next=node->prev=NULL;
	return node;
}
int Output(DoubleLink L_list)  //实现输出
{
	if(NULL==L_list)
		return -1;
	DoubleLink p=L_list;
	do
	{
		printf("%s ",p->data);
		p=p->next;
	}while(p!=NULL);
	puts("");
	return 0;
}

DoubleLink insert_head(DoubleLink L_list,ElemType value)  //实现头插
{
	DoubleLink node=Request_space();
	if(NULL==node)
		return L_list;  
	strcpy(node->data,value);
	if(NULL!=L_list)
	{
		node->next=L_list;
		L_list->prev=node;
	}
	L_list=node;
	return L_list;
}

DoubleLink insert_rear(DoubleLink L_list,ElemType value)  //实现尾插
{
	DoubleLink node=Request_space();
	strcpy(node->data,value);
	if(NULL==L_list)
		L_list=node;
	else
	{
		DoubleLink rear=L_list;
		while(rear->next!=NULL)
			rear=rear->next;
		rear->next=node;
		node->prev=rear;
	}
	return L_list;
}

DoubleLink delete_head(DoubleLink L_list)  //实现头删
{
	if(NULL==L_list)
		return NULL;
	if(L_list->next==NULL)
	{
		free(L_list);
		L_list=NULL;
	}
	else
	{
		DoubleLink p=L_list->next;
		strcpy(L_list->data,p->data);
		L_list->next=p->next;
		if(p->next!=NULL)
			p->next->prev=L_list;
		free(p);
		p=NULL;
	}
	return L_list;
}

DoubleLink delete_rear(DoubleLink L_list)  //实现尾删
{
	if(NULL==L_list)
		return NULL;
	if(L_list->next==NULL)
	{
		free(L_list);
		L_list=NULL;
	}
	else
	{
		DoubleLink rear=L_list;
		while(rear->next!=NULL)
			rear=rear->next;
		rear->prev->next=NULL;
		free(rear);
		rear=NULL;
	}
	return L_list;
}
int len_Llist(DoubleLink L_list)  //计算双向链表长度
{
	int count=0;
	if(NULL==L_list)
		return -1;
	while(L_list!=NULL)
	{
		count++;
		L_list=L_list->next;
	}
	return count;
}
DoubleLink rev_list(DoubleLink L_list)  //双向链表逆置
{
	if(NULL==L_list||L_list->next==NULL)
		return L_list;
	int len=len_Llist(L_list)-1;
	DoubleLink p=L_list->next;
	L_list->next=NULL;
	for(int i=0;i<len;i++)
	{
		DoubleLink q=p;
		p=p->next;
		q->prev=q->next;
		q->next=L_list;
		L_list=q;
	}
	return L_list;
}

主函数 main.c

#include "head.h"
int main(int argc, const char *argv[])
{
	DoubleLink L_list=NULL;  //定义头指针变量,注意定义时一定要指向NULL
	int n;            //定义循环输入次数
	ElemType value;   //定义数据域元素
	int seat;  //定义元素位置

	printf("please enter n:");
	scanf("%d",&n);

 	for(int i=0;i<n;i++)  //头插
	{
		printf("please enter a value:");
		scanf("%s",value);
		L_list=insert_head(L_list,value);
	}
	
	for(int i=0;i<n;i++)  //尾插
	{	
		printf("please enter a value:");
		scanf("%s",value);
		L_list=insert_rear(L_list,value);
	}

	L_list=delete_head(L_list);  //头删
	L_list=delete_rear(L_list);  //尾删
	Output(L_list);


	L_list=rev_list(L_list);  //双向链表逆置
	Output(L_list);

	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python应用实例(二)数据可视化(二)

数据可视化&#xff08;二&#xff09; 1.随机漫步1.1 创建RandomWalk类1.2 选择方向1.3 绘制随机漫步图1.4 模拟多次随机漫步1.5 设置随机漫步图的样式 1.随机漫步 使用Python来生成随机漫步数据&#xff0c;再使用Matplotlib以引人瞩目的方式将这些数据呈现出来。随机漫步是…

vscode远程连接提示:过程试图写入的管道不存在(删除C:\Users\<用户名>\.ssh\known_hosts然后重新连接)

文章目录 复现过程原因解决方法总结 复现过程 我是在windows上用vscode远程连接到我的ubuntu虚拟机上&#xff0c;后来我的虚拟机出了点问题&#xff0c;我把它回退了&#xff0c;然后再连接就出现了这个问题 原因 本地的known_hosts文件记录服务器信息与现服务器的信息冲突了…

reggie优化06-项目部署

1、部署架构 2、部署环境 3、部署前端 4、部署后端 修改图片位置&#xff0c;并push至仓库

【System Verilog and UVM基础入门17】Using get_next_item()

从小父亲就教育我&#xff0c;做一个对社会有用的人&#xff01; 关于握手协议的文章&#xff0c;网上有很多很多&#xff0c;这篇文章是最原滋原味的介绍&#xff0c;希望可以帮助到有缘人&#xff01; uvm_driver #(REQ,RSP) The base class for drivers that initiate req…

k8s如何访问 pod 元数据

如何访问 pod 元数据 **我们在 pod 中运行容器的时候&#xff0c;是否也会有想要获取当前 pod 的环境信息呢&#xff1f;**咱们写的 yaml 清单写的很简单&#xff0c;实际上部署之后&#xff0c; k8s 会给我们补充在 yaml 清单中没有写的字段&#xff0c;那么我们的 pod 环境信…

Python:基于matplotlib与mayavi的3D可视化(点云+等值面)

文章目录 一、3D可视化常用方法二、三维图像在numpy、cv2、以及tifffile.imread中通道的区别三、项目实战 1、基于matplotlib的3D可视化&#xff08;体素体&#xff09; 2、基于mayavi的3D可视化2.0、mayavi使用指南&#xff08;鼠标&#xff09;2.1、mlab.points3d()参数详解…

青岛大学_王卓老师【数据结构与算法】Week05_10_顺序栈的操作3_学习笔记

本文是个人学习笔记&#xff0c;素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享&#xff0c; 另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权&#xff0c;请留言作删文处理。 课程视频链接&#xff1a; 数据结构与算法基础…

【区块链+体育】“数智化”的杭州亚运会,中创助力区块链技术发展

“智能”&#xff0c;是杭州亚运会的办赛理念之一。除了数字藏品开亚运先河&#xff0c;杭州亚组委充分应用区块链、大数据、人工智能等前沿技术&#xff0c;为观众提供从购票、出行、观赛到住宿、美食和旅游等“一站式”服务。 本次亚运会将全程智能陆续落到了实处&#xff0…

简述直线导轨的预压力

直线导轨的预压力是预先给予钢珠负荷力&#xff0c;通俗来说就是加大钢珠直径&#xff0c;利用钢珠和珠道之间负向间隙给予预压&#xff0c;这个举动可以提高直线滑轨的刚性和消除间隙&#xff0c;值得注意的一点是小规格建议选用轻预压以下的预压&#xff0c;避免因为预压选用…

【Spring Boot】Web开发 — Web开发简介

Web开发简介 首先介绍Spring Boot 提供的Web组件spring-boot-starter-web&#xff0c;然后介绍Controller和RestController注解&#xff0c;以及控制数据返回的ResponseBody注解&#xff0c;最后介绍Web配置&#xff0c;以便让读者对使用Spring Boot开发Web系统有初步的了解。…

C# 动态字典(可以随机实时增删访问,保证先入先出的字典)

如果你有以下需求&#xff1a; 1. 需要对Dictionary进行遍历的同时移除或者添加元素 2. 需要按顺序遍历Dictionary并且保证先入先出 3. 需要即时的获取字典内的元素数量&#xff0c;即时增删 如果你觉得好&#xff0c;请给我的框架点一个免费的star&#xff0c;球球啦 Yueh0607…

TX Barcode .NET for WPF Crack

TX Barcode .NET for WPF Crack 用于WPF软件的TX Barcode.NET包括一天完成的功能以及用于WPF的软件的2D条形码控制。 用于WPF的TX Barcode.NET的功能和属性&#xff1a; 它具有以下特性和属性&#xff0c;如&#xff1a; 常见的文字处理功能&#xff1a;它可以为用户和开发人员…

一百三十、海豚调度器——用DolphinScheduler定时调度HiveSQL任务

一、目标 用海豚调度器对Hive数仓各层数据库的SQL任务进行定时调度。比如&#xff0c;DWD层脱敏清洗表的动态插入数据、DWS层指标表的动态插入数据 二、工具版本 1、海豚调度器&#xff1a;apache-dolphinscheduler-2.0.5-bin.tar.gz 2、Hive&#xff1a;apache-hive-3.1.2…

selenium WebDriver 中的几种等待--sleep(),implicitly_wait(),WebDriverWait()

目录 强制等待:sleep() 隐式等待:implicitly_wait() 显示等待:WebDriverWait() 与until()或者until_not()方法结合使用 WebDriverWait与expected_conditions结合使用 显示等待,自定义等待条件 强制等待:sleep() import time sleep(5) #等待5秒 设置固定休眠时间&#x…

webpack打包

webpack打包 1、webpack再次打包2、webpack的入口和出口 1、webpack再次打包 背景&#xff1a;代码增加之后&#xff0c;如何打包呢&#xff1f; 1、确保在src/index.js引用和使用 2、重新执行yarn build打包命令 2、webpack的入口和出口 1、新建webpack.config.js配置文件 …

Redis的五大数据类型和各自的

- 字符串(String) string 数据结构是简单的 key-value 类型。简单动态字符串**&#xff08;simple dynamic string&#xff0c;SDS&#xff09;。相比于 C 的原生字符串&#xff0c;Redis 的 SDS 不光可以保存文本数据还可以保存二进制数据&#xff0c;并且获取字符串长度复杂度…

django框架向DRF框架演变过程详解

一、Django框架实现项目查询接口 主要知识点&#xff1a; Django框架视图函数 1、在 Django 项目中创建一个应用&#xff08;如果还没有创建&#xff09;&#xff1a; python manage.py startapp projects 2、在项目的 models.py 文件中定义项目模型 from django.db impor…

JavaWeb(5)——HTML、CSS、JS 快速入门

一、JavaScript 对象 二、JavaScript BOM对象 和 DOM对象 关于BOM主要对 Window 和 location 进行说明&#xff1a; 三、JavaScript 事件监听 事件绑定 常见事件 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">…

OpenCv之图像形态学

目录 一、形态学 二、图像全局二值化 三、自适应阈值二值化 四、腐蚀操作 五、获取形态学卷积核 六、膨胀操作 七、开运算 八、闭运算 一、形态学 定义: 指一系列处理图像形状特征的图像处理技术形态学的基本思想是利用一种特殊的结构元(本质上就是卷积核)来测量或提取输…

【SQL】计算每个人的完成率

目录 前提任务的完成率前三名拓展&#xff1a;达梦如何去实现除法有余数拓展&#xff1a;MySQL 任务的完成率前三名 前提 达梦数据库&#xff1a; select 1/3; # 0不要求四舍五入 任务的完成率前三名 # nick_name 人名 # finishNum 当前这个人的任务完成数 # total 当前这…