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

这篇具有很好参考价值的文章主要介绍了算法与数据结构(二)--【1】表的概念及其四种实现方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一.表是什么

二.用动态数组实现表

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

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


一.表是什么


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

重点:序列!简单说就是一长串的数据,与树和图区分开!
【2】相关概念:
表长:线性表中元素的个数,n=0时为空表。
算法与数据结构(二)--【1】表的概念及其四种实现方式,数据结构
【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);
} 
​
void IterInit(List L){
	L->curr=L->last->next;
}
void IterNext(List L) {
	L->curr=L->curr->next;
	if (L->curr==L->last) L->curr=L->curr->next;
}
int *CurrItem(List L) {
	if(L->n==0)return 0;
	else return &L->curr->next->element;
}
void InsertCurr(ListItem x,List L) {
	link y=NewNode();
	y->element=x;
	y->next=L->curr->next;
	L->curr->next=y;
	if(L->curr==L->last)
		L->last=y;
	L->n++;
}
int DeleteCurr(List L) {
	link q=L->curr;
	link p=g->next;
	q->next=p->next;
	if(p==L->last) {
		L->last=q;
		L->curr=L->curr->next;
	}
	int x=p->element;
	free(p);
	L->n--;
	return x;
}

​

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


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

#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");
}

到了这里,关于算法与数据结构(二)--【1】表的概念及其四种实现方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【数据结构与算法】单链表的排序算法(选择,冒泡,递归)

    目录 选择排序 冒泡排序 快速排序 合并两条链表并排序 选择排序 链表的选择排序思想与数组的排序类似,但是链表需要先找到里面最小或者最大的值,然后将这个值用改链语句进行操作 我们先看这个改链语句的操作(min是笔者打错了应该是max,但是图已经画好了就没有改)

    2024年02月04日
    浏览(56)
  • 【数据结构和算法】删除链表的中间节点

    Java基础合集 数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 三、代码 四、复杂度分析 这是力扣的 2095 题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。 慢慢开始链表的模块了

    2024年01月19日
    浏览(77)
  • 【数据结构与算法】单链表的插入和删除

    🔥 本文由 程序喵正在路上 原创,CSDN首发! 💖 系列专栏: 数据结构与算法 🌠 首发时间:2022年9月21日 🦋 欢迎关注🖱点赞👍收藏🌟留言🐾 🌟 一以贯之的努力 不得懈怠的人生 众所周知,顺序表中的每个结点中只存放数据元素,其优缺点为: 优点:可随机存取,存储

    2024年02月07日
    浏览(43)
  • 【数据结构与算法】二、线性表的顺序表示【硬核】

    图书表的顺序存储结构类型定义: 在调用函数的过程中,当形参为引用类型时,实参和形参占用了相同的空间 2.4.1 线性表的基本操作: 2.4.2 线性表L的初始化 2.4.3 销毁和清空线性表L 2.4.4 求线性表L的长度以及判断线性表L是否为空 2.4.5 顺序表的取值(根据位置i获取相应位置

    2023年04月26日
    浏览(53)
  • 【数据结构与算法】单链表的增删查改(附源码)

      这么可爱的猫猫不值得点个赞吗 😽😻 目录 一.链表的概念和结构 二.单链表的逻辑结构和物理结构 1.逻辑结构  2.物理结构 三.结构体的定义 四.增加 1.尾插   SListpushback 2.头插  SListpushfront 五.删除 1.尾删  SListpopback 2.头删  SListpopfront 六.查找  插入  释放   打印 1.查找

    2024年02月02日
    浏览(75)
  • 单链表的建立(头插法、尾插法)(数据结构与算法)

    如果要把很多个数据元素存到一个单链表中,如何操作? 1.初始化一个单链表 2. 每次取一个数据元素,插入到表尾/表头 尾插法建立的单链表元素顺序与输入数据集合的顺序相同,即按照输入数据的顺序排列。 使用尾插法建立单链表的一个常见应用是在计算机科学中进行数据

    2024年04月11日
    浏览(44)
  • 【数据结构与算法】一、数据结构的基本概念

    抽象数据类型(ADT)定义举例:Circle的定义 如何处理杂乱无章且多样化的数据: 数据元素 :数据中的个体被称为数据元素。 数据对象 :性质相同的数据元素组成的集合。 数据结构 :数据元素加上数据元素之间的关系,就形成了数据结构。 逻辑结构 :数据结构的逻辑模型。

    2023年04月17日
    浏览(99)
  • C语言简单的数据结构:单链表的有关算法题(2)

    接着我们介绍后面的三道题,虽然代码变多了但我们的思路更加通顺了 题目链接:https://leetcode.cn/problems/merge-two-sorted-lists/ 创建新链表,遍历原链表,将节点值小的进行尾插到新链表中 这里要多次进行对NULL的判断,开始传入列表,中间newHead的判断,循环出来一个为NULL的判断

    2024年04月15日
    浏览(64)
  • 数据结构-二叉链表的结构与实现

    目录 一、引言 二、什么是二叉链表 三、二叉链表的结构 四、二叉链表的实现 1. 创建二叉链表 2. 遍历二叉链表 3. 插入节点 4. 删除节点 五、应用场景 六、总结 七、代码示例 数据结构是计算机科学中的重要概念,它是计算机程序设计的基础。二叉链表是一种常见的数据结构

    2024年02月08日
    浏览(49)
  • 【数据结构与算法——TypeScript】算法的复杂度分析、 数组和链表的对比

    什么是算法复杂度(现实案例)? ❤️‍🔥 前面已经解释了什么是算法? 其实就是解决问题的一系列步骤操作、逻辑。 ✅ 对于同一个问题,我们往往有很多种解决思路和方法,也就是可以采用不同的算法。 举个例子(现实例子):在一个庞大的图书馆中,我们需要找一本书

    2024年02月14日
    浏览(53)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包