c语言数据结构与算法--简单实现线性表(顺序表+链表)的插入与删除

news2024/11/25 23:56:46

        老规矩,点赞+评论+收藏+关注!!!

目录

线性表

其特点是:

算法实现:

运行结果展示

链表

插入元素:

删除元素:

算法实现

运行结果

        线性表是由n个数据元素组成的有限序列,每个元素都有唯一的下标,下标从0开始递增。线性表的元素之间存在一对一的线性关系,即除首元素外,每个元素有且只有一个前驱元素,除尾元素外,每个元素有且只有一个后继元素。线性表可以通过顺序存储或链式存储来实现。线性表的基本操作包括初始化、创建、增加、删除和查找等。

        顺序表和链表是线性表的两种实现方式,都是用来存储逻辑关系为“一对一”的数据。它们的相同点是:都是线性表结构;元素逻辑存储上是连续的;每个元素都有唯一的前驱和唯一的后继。它们的不同点是:底层存储空间不一样,顺序表底层存储空间是连续的,而链表则是不连续的;插入和删除方式不同,顺序表任意位置进行插入和删除操作,需要搬运大量的元素,效率低,时间复杂度为O(N)。顺序表集中存储数据,适合访问、遍历数据,在数据量确定时空间利用率高;链表通过指针链接数据,适合插入、删除数据,在数据量不确定时空间利用率高。

线性表

线性表的顺序表示是指用一组地址连续的存储单元依次存储线性表的数据元素。

其特点是:

1.第 i 个元素 a i 的存储位置可以用公式计 LOC(a i) = LOC(a1)+(i-1)*L

其中 LOC(a1)第一个元素a1 的存储位置,L 每个元素需占的存储单元

2.表中相邻的元素 a i a i+1赋以相邻的存 储位置 LOC(a i)和 LOC(a i+1)

3.是一种随机存储结构:只要知道线性表的 起始位置就可随机存取线性表中的任一元素。

        当我们要在线性表的顺序存储结构上的第 i 个位置上插入一个元素时,必须先将 线性表第 i 个元素之后的所有元素依次后移一个位置,以便腾空一个位置,再把新元素插入到该位置。若要删除第 i 个元素时,也必须把第 i 个元素之后的所有元素前 移一个位置。

算法实现:

1、引入头文件、定义结构体

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INIT_SIZE 100  //初始分配量
#define INCRE_SIZE 10  //分配增量

typedef struct {
	int *pList;
	int length;
	int listSize;
}SqList;

2、创建顺序表

//顺序表的创建
void initial(SqList &L) {  //使pList指向连续存储空间的首地址
	L.pList = (int*)malloc(INIT_SIZE * sizeof(int));
	L.length = 0;  //目前元素的个数为0
	L.listSize = INIT_SIZE;  //空间最大存储的数量
}

3、定义插入函数

//第i个元素前插入e
void insert(int e,SqList &L,int i) {
	if (i <= L.length || L.length < L.listSize) {
		//将第i个元素开始依次往后移动一个位置,将L[i-1]的位置腾出
		for (int curIndex = L.length - 1; curIndex >= i - 1; --curIndex) {
			L.pList[curIndex + 1] = L.pList[curIndex];
		}
		L.pList[i - 1] = e;
		++L.length;  //多存了个数据,元素个数加一
	}
}

4、定义删除函数

void delete_(SqList &L,int i) {
	if (i <= L.length || L.length < L.listSize) {
		//将第i个元素开始依次往后移动一个位置
		for (int curIndex = i-1; curIndex <= L.length; ++curIndex) {
			L.pList[curIndex] = L.pList[curIndex + 1];
		}
		--L.length;  //多存了个数据,元素个数减一
	}
}

5、初始化输入表

//初始输入表
void initial_list(SqList* L) {
	int n,d;
	printf("请输入输入数字个数n(大于1的整数):");
	scanf_s("%d", &n);
	while (1) {
		if (n <= 0) {
			printf("请输入大于0的整数!!!");
			scanf_s("%d", &n);
		}
		else {
			break;
		}
	}
	//printf("%d", n);
	for (int i = 0; i <= n-1; i++) {
		printf("请输入第%d个数:",i+1);
		scanf_s("%d",&d);
		L->pList[i] = d;
	}
	L->length = n;
}

6、定义打印函数

//打印数组
void print_function(SqList L) {
	for (int i = 0; i < L.length; i++) {
		printf("%d  ", L.pList[i]);
	}
	printf("\n");
}

7、主函数

int main() {
	SqList L;
	initial(L);
	initial_list(&L);
	printf("原数组:\n");
	print_function(L);
	printf("\n");
	while (1) {
		printf("请输入0/1/2对线性表进行操作(0是退出,1是插入,2是删除):\n");
		int num;
		scanf("%d", &num);
		if (num == 1) {
			printf("现在进入插入环节,请指定插入元素与插入位置:\n");
			int i, n;
			scanf("%d %d", &i, &n);
			insert(i, L, n);
			printf("插入后的数组:\n");
			print_function(L);
		}
		else if (num == 2) {
			printf("现在进入删除环节,请指定删除要元素位置:\n");
			int n;
			scanf("%d",&n);
			delete_(L, n);
			printf("删除后的数组:\n");
			print_function(L);
		}
		else if (num == 0) {
			break;
		}
		else {
			printf("请输入正确的操作(输入0/1/2)\n");
		}
		}
	return 0;
}

运行结果展示

        输入数字个数n,并输入这n个数

        选择下一步操作(0退出,1插入,2删除)

链表

双向链表

        结点有两个指针域:一个指向直接后继,另一个指向直接前驱。目的是克服单链 表的单向寻查的缺点。

插入元素:

        当插入数据元素时,首先生成一个结点,结点的数据域为插入的元素;然后找到元素的插入位置;最后修改指针域。例如下图中,在 p 结点后插入新生 成结点 s,则修改指针的语句为:

s ->data = e; s->next = p->next;  p->next = s;

删除元素:

        当删除数据元素时,仅修改待删除结点的前一个结点的指针。例如下 图中,待删除的结点为 q,q 的前一个结点为 p,删除后结点 q 的数据赋给 e,则修改 指针的语句为:

q= p ->next;  p->next = q->next; e = q-> data;  free(q);

算法实现

1、头文件、结构体的定义

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>  
#include <stdlib.h>  

typedef struct Node {
    int data;
    struct Node* prior;
    struct Node* next;
} Node;

2、双链表中添加节点

// 在双链表末尾添加节点  
void append(Node** head, int data) {
    Node* newNode = createNode(data);
    if (*head == NULL) {
        *head = newNode;
    }
    else {
        Node* temp = *head;
        while (temp->next != NULL) {
            temp = temp->next;
        }
        temp->next = newNode;
        newNode->prior = temp;
    }
}

3、定义打印函数

// 打印双链表  
void printList(Node* head) {
    Node* temp = head;
    while (temp != NULL) {
        printf("%d ", temp->data);
        temp = temp->next;
    }
    printf("\n");
}

4、指定位置插入元素

// 在指定位置插入节点  
void insertAtPosition(Node** head, int position, int data) {
    Node* newNode = createNode(data);
    if (position == 1) {
        newNode->next = *head;
        if (*head != NULL) {
            (*head)->prior = newNode;
        }
        *head = newNode;
    }
    else {
        Node* temp = *head;
        for (int i = 1; temp != NULL && i < position - 1; i++) {
            temp = temp->next;
        }
        if (temp == NULL) {
            printf("Position out of bounds\n");
            free(newNode);
            return;
        }
        newNode->next = temp->next;
        newNode->prior = temp;
        if (temp->next != NULL) {
            temp->next->prior = newNode;
        }
        temp->next = newNode;
    }
}

5、删除元素

// 删除指定值的节点  
void deleteValue(Node** head, int data) {
    Node* temp = *head;
    Node* prior = NULL;

    while (temp != NULL && temp->data != data) {
        prior = temp;
        temp = temp->next;
    }
    if (temp == NULL) {
        printf("Value not found\n");
        return;
    }
    if (prior == NULL) {
        *head = temp->next;
    }
    else {
        prior->next = temp->next;
    }
    if (temp->next != NULL) {
        temp->next->prior = prior;
    }
    free(temp);
}

6、主函数

int main() {
    Node* list = NULL;
    int n, choice, position, data;
    printf("请输入数字n: ");
    scanf("%d", &n);
    printf("请输入%d个数字:\n", n);
    for (int i = 0; i < n; i++) {
        int num;
        scanf("%d", &num);
        append(&list, num);
    }
    printf("当前列表: ");
    printList(list);
    printf("请输入1和2选择操作(1:插入 2:删除)\n");
    scanf("%d", &choice);
    if (choice == 1) {
        printf("请输入插入位置和插入的数字: ");
        scanf("%d %d", &position, &data);
        insertAtPosition(&list, position, data);
    }
    else if (choice == 2) {
        printf("请输入要删除的数字: ");
        scanf("%d", &data);
        deleteValue(&list, data);
    }
    else {
        printf("无效选择\n");
    }
    printf("最终列表: ");
    printList(list);
    // 释放链表内存  
    Node* temp;
    while (list != NULL) {
        temp = list;
        list = list->next;
        free(temp);
    }
    return 0;
}

运行结果

        输入数字个数n,并依次输入这n个元素

        选择下一步操作(1插入,2删除)

您的点赞和关注是我持续更新下去的动力!!

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

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

相关文章

textureLod lod的确定

1. 自动计算导数方法 float calculateLOD(sampler2D tex, vec2 uv) { // 计算纹理坐标的导数 vec2 dUVdx dFdx(uv); vec2 dUVdy dFdy(uv); // 计算纹理大小 vec2 textureSize textureSize(tex, 0); // 0表示基础mipmap级别 // 计算LOD float maxDeriv max(length(…

C++数据结构与算法

C数据结构与算法 1.顺序表代码模版 C顺序表模版 #include <iostream> using namespace std; // 可以根据需要灵活变更类型 #define EleType intstruct SeqList {EleType* elements;int size;int capacity; };// Init a SeqList void InitList(SeqList* list, int capa…

SSH 反向端口转发-R

近期和同学聊到了他遇到的一个问题&#xff1a; 本地机器A&#xff0c;远程开发机C&#xff0c;机器A需要通过ssh连接开发机C进行开发&#xff0c;ssh直连不通&#xff0c;SCP传输文件的话就比较费劲&#xff0c;需要通过跳板机B&#xff0c;经过跳板机这一步骤可用&#xff0…

实时质检系统—静音检测功能设置流程

设置流程 1. 设置静音检测时间 在实时质检系统中&#xff0c;有一静音检测功能&#xff1a;可以对主叫或被叫在接通后的规定时间内开启静音检测。例&#xff1a;被叫静音检测配置设置了10&#xff0c;那么质检电话在接通后的10秒内&#xff0c;开启静音检测&#xff0c;如果被…

生成式UI 动态化SDK的研发(二)--实现垂直布局、水平布局以及文字组件

文章目录 1. 概述2. 效果展示2.1 垂直布局容器(Column)2.2 水平布局容器(Row )2.3 本文示例动态化模板DSL 3. 生成式UI 动态化SDK的渲染流程4. Column和Row组件实现4.1 Column组件4.1.1 视图的渲染4.1.2 事件解析绑定 4.2 Row组件4.3 文字组件(Text) 5. 源码地址 1. 概述 在前…

JavaScript中的this指向绑定规则(超全)

JavaScript中的this指向绑定规则&#xff08;超全&#xff09; 1.1 为什么需要this? 为什么需要this? 在常见的编程语言中&#xff0c;几乎都有this这个关键字&#xff08;Objective-C中使用的是self),但是在JavaScript中的this和常见的面向对象语言中的this不太一样 常见面…

Vision Transformer(VIT模型)

【11.1 Vision Transformer(vit)网络详解-哔哩哔哩】 https://b23.tv/BgsYImJ 工作流程&#xff1a; ①将输入的图像进行patch的划分 ②Linear Projection of Flatted patches&#xff0c;将patch拉平并进行线性映射生成token ③生成CLS token&#xff08;用向量有效地表示整…

2024年11月最新 Alfred 5 Powerpack (MACOS)下载

在现代数字化办公中&#xff0c;我们常常被繁杂的任务所包围&#xff0c;而时间的高效利用成为一项核心需求。Alfred 5 Powerpack 是一款专为 macOS 用户打造的高效工作流工具&#xff0c;以其强大的定制化功能和流畅的用户体验&#xff0c;成为众多效率爱好者的首选。 点击链…

C#里怎么样检测文件的属性?

C#里怎么样检测文件的属性? 对于文件来说,在C#里有一种快速的方法来检查文件的属性。 比如文件是否已经压缩, 文件是否加密, 文件是否是目录等等。 属性有下面这么多: 例子演示如下: /** C# Program to View the Information of the File*/ using System; using Syste…

网络安全,文明上网(4)掌握网络安全技术

前言 在数字化时代&#xff0c;个人信息和企业数据的安全变得尤为重要。为了有效保护这些宝贵资产&#xff0c;掌握一系列网络安全技术是关键。 核心技术及实施方式 1. 网络监控与过滤系统&#xff1a; 这些系统构成了网络防御体系的基石&#xff0c;它们负责监控网络通信&…

Vue 项目中如何使用FullCalendar 时间段选择插件(类似会议室预定、课程表)

本文中是基于VUEelementui项目中实现的前后端分离的前端功能部分&#xff1a; 插件的官方文档&#xff1a;FullCalendar 1.安装对应依赖&#xff08;统一安装版本为6.15&#xff09; npm install --save fullcalendar/core6.15 npm install --save fullcalendar/daygrid6.…

Oracle SQL优化③——表的连接方式

前言 表&#xff08;结果集&#xff09;与表&#xff08;结果集&#xff09;之间的连接方式非常重要&#xff0c;如果CBO选择了错误的连接方式&#xff0c;本来几秒就能出结果的SQL可能执行一天都执行不完。如果想要快速定位超大型SQL性能问题&#xff0c;就必须深入理解表连接…

小程序25- iconfont 字体图标的使用

项目中使用到图标&#xff0c;一般由公司设计进行设计&#xff0c;设计好后上传到阿里巴巴矢量图标库 日常开发过程中&#xff0c;也可以通过 iconfont 图标库下载使用自带的图标 补充&#xff1a;使用 iconfont 图标库报错&#xff1a;Failed to load font 操作步骤&#xff…

Java基于SpringBoot+Vue的藏区特产销售平台

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

selinux及防火墙

selinux说明 SELinux 是 Security-Enhanced Linux 的缩写&#xff0c;意思是安全强化的 linux 。 SELinux 主要由美国国家安全局&#xff08; NSA &#xff09;开发&#xff0c;当初开发的目的是为了避免资源的误用。 httpd进程标签&#xff08;/usr/share/nginx/html &#…

详细探索xinput1_3.dll:功能、问题与xinput1_3.dll丢失的解决方案

本文旨在深入探讨xinput1_3.dll这一动态链接库文件。首先介绍其在计算机系统中的功能和作用&#xff0c;特别是在游戏和输入设备交互方面的重要性。然后分析在使用过程中可能出现的诸如文件丢失、版本不兼容等问题&#xff0c;并提出相应的解决方案&#xff0c;包括重新安装相关…

生成对抗网络模拟缺失数据,辅助PAMAP2数据集仿真实验

PAMAP2数据集是一个包含丰富身体活动信息的数据集&#xff0c;它为我们提供了一个理想的平台来开发和测试HAR模型。本文将从数据集的基本介绍开始&#xff0c;逐步引导大家通过数据分割、预处理、模型训练&#xff0c;到最终的性能评估&#xff0c;在接下来的章节中&#xff0c…

IEC61850读服务器目录命令——GetServerDirectory介绍

IEC61850标准中的GetServerDirectory命令是变电站自动化系统中非常重要的一个功能&#xff0c;它主要用于读取服务器的目录信息&#xff0c;特别是服务器的逻辑设备节点&#xff08;LDevice&#xff09;信息。以下是对GetServerDirectory命令的详细介绍。 目录 一、命令功能 …

基于CNN+RNNs(LSTM, GRU)的红点位置检测(pytorch)

1 项目背景 需要在图片精确识别三跟红线所在的位置&#xff0c;并输出这三个像素的位置。 其中&#xff0c;每跟红线占据不止一个像素&#xff0c;并且像素颜色也并不是饱和度和亮度极高的红黑配色&#xff0c;每个红线放大后可能是这样的。 而我们的目标是精确输出每个红点的…

前端:JavaScript (学习笔记)【2】

目录 一&#xff0c;数组的使用 1&#xff0c;数组的创建 [ ] 2&#xff0c;数组的元素和长度 3&#xff0c;数组的遍历方式 4&#xff0c;数组的常用方法 二&#xff0c;JavaScript中的对象 1&#xff0c;常用对象 &#xff08;1&#xff09;String和java中的Stri…