算法与数据结构(二)--【1】表的概念及其四种实现方式

news2024/9/21 7:05:01

一.表是什么


【1】定义:表,又称为线性表。线性表L是n个相同类型数据元素a(1),a(2),...,a(n)组成的有限序列。
【2】相关概念:
表长:线性表中元素的个数,n=0时为空表。

【3】基本运算(共七种):
ListEmpty(L):测试表L是否为空
ListLength(L):表L的长度
ListLocate(x,L):元素x在表L中的位置。若x在表中重复出现多次,则返回最前面的x的位置。
ListRetrieve(k,L):返回表L的位置k处的元素。表中没有位置k是,该运算无定义。
ListInsert(k,x,L):在表L的位置k之后插入元素x,并将原来占据该位置的元素及其后面的元素依次后移一个位置。若表中没有位置k,则该运算无定义。
ListDelete(k,L):从表L中删除位置k处的元素,并返回被删除的元素。如果表中没有位置k时,则该运算无定义。
PrintList(L):将表L中所有元素按位置的先后次序打印输出。

二.用动态数组实现表


1.顺序表概念
用一组地址连续的存储单元(数组)存放一个线性表叫顺序表
2.实现代码(就是在编写上述七种基本运算的函数的基础上,又因为是动态数组,需要增加初始化函数和释放空间的函数,所以这里实现了九种函数)【这里存储的元素取int】

#include<stdio.h>
#include<stdlib.h> 
//定义(因为还有表长,最大长度等属性,所以可用结构体或类来封装属性, 
//又因为我们是使用c语言,没有类,所以我们把表定义为结构体 
typedef struct alist *List;//表指针 
typedef struct alist{
	int n;//表长,当表为空时,n=0
	int maxsize;//表示线性表的最大长度
	int *table;//表元素数组,这里使用的是int型,当然也可以其他类型 
};  
//1.表结构初始化
//分配大小为size的空间给表数组table,并返回初始化为空的表。
List ListInit(int size){
	List L;
	L=(List)malloc(sizeof(alist));//作用? 
	L->table=(int *)malloc(size*sizeof(int));
	L->maxsize=size;
	L->n=0;
	return L; 
} 
//2.判断表L是否为空
int ListEmpty(List L){
	if(L->n==0)
		return true;
	else
		return false; 
} 
//3.求表L的长度
int GetLength(List L){
	return L->n;
} 
//4.返回表L的位置k处的元素
int ListRetrieve(int k,List L){
	if(k<1||k>L->n)
		return -2147483648;//判断k值是否合理,若不合理,返回负数最小值 
	return L->table[k-1];
}
//5. 返回元素x在表中的第一个位置,当元素x不在表中时返回0
int ListLocate(int x,List L){
	for(int i=0;i<L->n;i++){
		if(L->table[i]==x)
			return i++;//真实位置比索引多1 
	}
	return 0;//元素不在表中返回0 
} 
//6.在表L的位置k之后插入元素x 
void ListInsert(int k,int x,List L){
	if(k<0||k>L->n)
		return;//判断k值是否合理,若不合理,返回
	for(int i=L->n-1;i>=k;i--)
		L->table[i+1]=L->table[i];
	L->table[k]=x;
	L->n++;
}
//7.从表L中删除位置k处的元素
int ListDelete(int k,List L){
	if(k<1||k>L->n)
		return -2147483648;
	int x=L->table[k-1];
	for(int i=k;i<L->n;i++)
		L->table[i-1]=L->table[i];
	L->n--;
	return x;
}
//8.按位置次序输出表L中元素
void PrintList(List L){
	for(int i=0;i<L->n;i++)
		printf("%d ",L->table[i]);
	printf("\n");
} 
//9.释放动态分配的数组空间
void ListFree(List L){
	free(L->table);
	free(L);
} 

三.用链表(指针)实现表


1.链表概念
用一组任意的存储单元存储线性表的数据元素,利用指针将其串联在一起,实现了用不相邻的存储单元存放逻辑上相邻的元素。以这种链式存储结构存储的表称为链表。
2.用动态数组实现表的优缺点(比较):
优点:存储空间紧凑;逻辑相邻,物理相邻,无须为表示表中元素之间的顺序关系增加额外的存储空间;可随机存取任一元素,查找速度快
缺点:插入和删除耗时;表容量难以扩充
3.实现代码【这里存储的元素取int】

#include<stdio.h>
#include<stdlib.h>
//定义 
typedef struct node* link;//表结点指针类型 
typedef struct node{//表结点类型 
	int element;//表元素 
	link next;//指向下一写点的指针 
}Node;
typedef struct llist *List;//单链表指针类型
typedef struct llist{//单链表类型
	//链表表首指针,当前结点指针,链表表尾指针 
	link first,curr,last; 
}Llist; 
//1.产生一个新结点 
link NewNode(){
	return (link)malloc(sizeof(Node));
}
//2.表结构初始化
分配大小为size的空间给表数组table,并返回初始化为空的表。 
List ListInit(){
	List L=(List)malloc(sizeof *L);
	L->first=0;
	return L;
} 
//3.判断表L是否为空
//只要看表首指针first是否为空指针 
int ListEmpty(List L){
	return L->first==0;
}
//3.求表L的长度
int ListLength(List L){
	int len=0;
	link p=L->first;
	//通过对表L进行线性扫描计算 
	while(p){
		len++;
		p=p->next;
	}
	return len;
}
//4.返回表L的位置k处的元素  
int ListRetrieve(int k,List L){
	if(k<1)
		exit(1);//不正常退出 
	link p=L->first;
	int i=1;
	while(i<k&&p){
		p=p->next;
		i++;
	}
	return p->element; 
} 
//5. 返回元素x在表中的第一个位置,当元素x不在表中时返回0
int ListLocate(int x,List L){
	int i=1;
	link p=L->first;
	while(p&&p->element!=x){
		p=p->next;
		i++;
	} 
	return p?i:0;
}
//6.在表L的位置k之后插入元素x 
void ListInsert(int k,int x,List L){
	if(k<0)
		exit(1);
	link p=L->first;
	for(int i=1;i<k&&p;i++)
		p=p->next;
	link y=NewNode();
	y->element=x;
	if(k){
		y->next=p->next;
		p->next=y;
	}else{
		y->next=L->first;
		L->first=y;
	}
}
//7.从表L中删除位置k处的元素
int ListDelete(int k,List L){
	if(k<1||!L->first)
		exit(1);
	link p=L->first;
	if(k==1)
		L->first=p->next;
	else{
		link q=L->first;
		for(int i=1;i<k-1&&q;i++)
			q=q->next;
		p=q->next;
		q->next=p->next;
	}
	int x=p->element;
	free(p);
	return x;
}
//8.按位置次序输出表L中元素
void PrintList(List L){
	for(link p=L->first;p;p=p->next)
		printf("%d",p->element);
} 

四.用间接寻址方法实现表


1.实现:让动态数组中原来存储元素的地方改为存储指向元素的指针​​​​​。

2.优点:就是在动态数组实现表的基础上进行优化。
这时候你会疑问这只是让动态数组中原来存储元素的地方改为存储指向元素的指针,然而进行各种增删改查的算法仍然与动态数组一模一样​​​​​,只是你要操作元素还需要通过先获取指针再来操作元素,这样的话从直接操作元素变为间接操作,为什么会更好?
这是因为在实现在位置k后插入元素和删除位置为k的元素这两个方法的时候,不实际移动元素而只移动指向元素的指针。虽然算法所需的计算时间O(n)仍然相同,但在每个元素占用的空间较大时,该算法比数组实现的表的插入算法快得多。
简单说就是移动指针的速度比直接移动元素的速度快。元操作的速度快。
3.实现代码【这里存储的元素取int】

#include<stdio.h>
#include<stdlib.h>
//定义
typedef int *addr;//这里表元素的类型假设为int
typedef struct indlist *List;
typedef struct indlist {
	int n;//表长
	int curr;//当前位置
	int maxsize;//数组上界
	addr *table;//存储表元素指针的数组
} Indlist;
addr NewNode() {
	return (addr)malloc(sizeof(addr));
}
//1.表结构初始化
//分配大小为size的空间给表数组table,并返回初始化为空的表。
List ListInit(int size) {
	List L=(List)malloc(sizeof *L);
	L->n=0;
	L->maxsize=size;
	L->table=(addr*)malloc(size*sizeof(addr));
	return L;
}
//2.判断表L是否为空
int ListEmpty(List L) {
	return L->n==0;
}
//3.求表L的长度
int ListLength(List L) {
	return L->n;
}
//4.返回表L的位置k处的元素
int ListRetrieve(int k,List L) {
	if(k<1||k>L->n)
		exit(1);
	return *L->table[k-1];
}
//5. 返回元素x在表中的第一个位置,当元素x不在表中时返回0
int ListLocate(int x,List L) {
	for(int i=0; i<L->n; i++) {
		if(*L->table[i]==x)
			return ++i;
	}
	return 0;
}
//6.在表L的位置k之后插入元素x 
void ListInsert(int  k,int x,List L) {
	if(k<0||k>L->n)
		exit(1);
	if(L->n==L->maxsize)
		exit(1);
	for(int i=L->n-1; i>=k; i--)
		L->table[i+1]=L->table[i];
	L->table[k]=NewNode();
	*L->table[k]=x;
	L->n++;
}
//7.从表L中删除位置k处的元素
int ListDelete(int k,List L) {
	int x;
	addr p;
	if (k<1 || k>L->n) 
		exit(1);
	p = L->table[k-1];
	x=*p;
	for (int i=k; i<L->n; i++) 
		L->table[i-1]=L->table[i];
	L->n--;
	free(p);
	return x;
}
//8.按位置次序输出表L中元素
void PrintList(List L){
	for(int i=0;i<L->n;i++)
		printf("%d ",*L->table[i]);
	printf("\n");
}

五.用游标实现表

比较少用,先跳过,以后有时间再添加。

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

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

相关文章

Linux Vim提示:E325: ATTENTION 解决方案

提示&#xff1a; 这是由于我们异常退出vim界面 程序异常关闭导致的 解决&#xff1a; 在这种情况下&#xff0c;您可以根据以下选项来解决问题&#xff1a; [O]pen Read-Only&#xff1a;以只读模式打开文件。这意味着您不能编辑文件&#xff0c;但可以查看其内容。选择此选…

Nacos (2.0版本之后)状态异常集群节点状态异常

在nacos 2.0 之后正常部署后节点状态仅有一个正常,其余均为DOWN 或者SUSPICIOUS 状态 查看日志后发现 ERROR Server check fail, please check server 192.168.172.104 ,port 9849 is available , error {} 其实是nacos 相互之间不能正常通信造成的,nacos客户端升级为2.x版…

2023-07-11:给定正整数 n, 返回在 [1, n] 范围内具有 至少 1 位 重复数字的正整数的个数。 输入:n = 100。 输出:10。

2023-07-11&#xff1a;给定正整数 n&#xff0c; 返回在 [1, n] 范围内具有 至少 1 位 重复数字的正整数的个数。 输入&#xff1a;n 100。 输出&#xff1a;10。 答案2023-07-11&#xff1a; 函数的主要思路如下&#xff1a; 1.若n小于等于10&#xff0c;则直接返回0&…

漏洞复现 || SolarView Compact 存在任意命令执行漏洞(CVE-2023-23333)

免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失,均由使…

k8s+springboot+CronJob 定时任务部署

kubernetesspringbootCronJob 定时任务配置如下代码&#xff1a; cronjob.yaml k8s 文件 apiVersion: batch/v1 kind: CronJob metadata:name: k8s-springboot-demonamespace: rz-dt spec:failedJobsHistoryLimit: 3 #执行失败job任务保留数量successfulJobsHistoryLimit: 5 …

etcd的使用

什么是etcd ETCD是一个分布式、可靠的key-value存储的分布式系统&#xff0c;用于存储分布式系统中的关键数据&#xff1b;当然&#xff0c;它不仅仅用于存储&#xff0c;还提供配置共享及服务发现&#xff1b;基于Go语言实现 。 etcd的特点 完全复制&#xff1a;集群中的每…

Spring Boot 系列1 -- 概念、创建和使用

目录 1. 什么是Spring Boot? 2. Spring Boot 的优点 3. Spring Boot 项目的创建 3.1 使用IDEA创建 3.2 网页版创建 4. 项目目录和项目运行 4.1 项目目录 4.2 运行项目 4.3 使用Spring Boot项目实现网页输出Hello World 5. 路径问题 1. 什么是Spring Boot? Spring …

【vue+vant使用请求loading】【vant如何关闭Toast】

vuevant使用请求loading 文档&#xff1a;https://vant-contrib.gitee.io/vant/v2/#/zh-CN/toast 需求&#xff1a;目前需求是在请求中使用toast-loading&#xff0c;请求完成后关闭这个toast&#xff1b; 问题&#xff1a;vant如何关闭toast呢&#xff1f; 解决&#xff1a…

【UE4 C++】05-添加组件

在“SCharacter.h”中添加如下代码&#xff0c;从而为“SCharacter”添加弹簧臂和摄像机组件。 在“SCharacter.cpp”中添加如下代码 重新生成解决方案 打开虚幻编辑器&#xff0c;此时在视口中可以看到新添加的摄像机组件&#xff0c;摄像机处于世界坐标原点&#xff0c;并不会…

VisProg解析:根据自然语言指令解决复杂视觉任务

VisProg&#xff1a;根据自然语言指令解决复杂视觉任务 1. 介绍 VisProg 是一种神经符号系统&#xff0c;可以根据自然语言指令解决复杂的组合视觉任务。VisProg 使用 GPT3 的上下文学习能力来生成 Python 程序&#xff0c;然后执行这些程序以获得解决方案和全面且可解释的基…

前端学习——css盒子模型、css3新特性、伪类、布局0711TODO

样式还是得具体使用才能理解&#xff0c;不然会忘记也理解不透彻&#xff1b;还有定位&#xff0c;元素溢出&#xff0c;浮动&#xff0c;布局水平&垂直对齐&#xff1a; css3新特性 1过渡 2 动画 3 2D、3D转换 伪类 三种定位方式 弹性布局/栅格布局

VS+QT+OpenCV+C++多线程多摄像头视频监控采集窗体

程序示例精选 VSQTOpenCV多线程多摄像头视频监控采集窗体 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<VSQTOpenCV多线程多摄像头视频监控采集窗体>>编写代码&#xff0c;代码…

【Matlab】智能优化算法_算数优化算法AOA

【Matlab】智能优化算法_算数优化算法AOA 1.背景介绍2.数学模型2.1 初始化阶段2.2 勘探阶段2.3 开采阶段 3.文件结构4.伪代码5.详细代码及注释5.1 AOA.m5.2 func_plot.m5.3 Get_F.m5.4 initialization.m5.5 main.m 6.运行结果7.参考文献 1.背景介绍 算术是数论的基本组成部分&a…

MySQL的表操作DML,DDL

建表 mysql> create table work(-> dept_id int(11) not null comment 部门号,-> staff_id int(11) not null comment 职工号,-> work_time date not null comment 工作时间,-> wage float(8.2) not null comment 工资,-> poli_face varchar(20) not null …

软考A计划-系统集成项目管理工程师-项目成本管理-中

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

如何在本地组策略编辑器中启用或禁用剪贴板历史记录

复制粘贴是我们大家都会做的事情,可能一天要做多次。但是,如果你需要一次又一次地复制同样的几件事,你该怎么办?如何在设备上复制内容? 从Windows 10版本17666开始,微软正在解决这一问题,并将剪贴板提升到一个新的水平,只需按下Win+V,你将获得全新的剪贴板体验。 你…

session共享问题和其他常见问题及解决方案

目录 1.shirospringboot中session的共享问题 1.1 如何解决session共享问题 2. 解决前端不支持cookie的效果 2.1.如何把sessionId放入请求头 2.2.重写DefaultWebSessionManager的方法 3.设置前端前置路由守卫 4.如何防止恶意重复登录 5.退出 6.获取当前登录用户的信息 …

jQuery根据数据动态创建表格:列固定,行超出滚动条,绑定td点击事件等

示例如图&#xff0c;代码如下: html: <div class"layui-row" id"avTableulL"><ul></ul></div><div id"avTableulR"><div id"avTableulT"><ul></ul></div><div id"avT…

【华为认证】HCIP-Datacom 2023最新题库

正在备考华为认证的小伙伴应该知道&#xff0c;除了理论知识外&#xff0c;刷题也相当重要&#xff0c;周工这里有一份HCIAHCIP-Datacom带解析的最新题库 点赞留言 即可领取。 1. &#xff08;多选题&#xff09;ISIS的Hello报文主要分为哪几种类型? A.P2P LAN IIH B.…

UnityVR--机械臂场景12-简单流水线应用4

目录 一. 手爪 二. 红外线传感器 三. 工件生成器 四. 总结 上一篇已经实现了机械臂各种动作的控制&#xff0c;本篇实现一下其余的组成部分&#xff0c;比如手爪、传感器和自动放置工件等。 一. 手爪 手爪的模型调整就不多说了&#xff0c;需要设置的是Rigidbody、Collide…