实验一 线性表的顺序存储与实现_【自考】数据结构中的线性表,期末不挂科指南,第2篇

7f6464c9d941aa5d96710d953009b966.png

线性表

这篇博客写的是线性表相关的内容,包括如下部分,先看下有木有期待

  1. 啥是线性表
  2. 线性表的顺序存储
  3. 线性表的基本运算在顺序表上的实现
  4. 线性表的链式存储
  5. 线性表的基本运算在单链表上的实现
  6. 循环链表与双向循环链表

Over,内容还蛮多的!~  ̄□ ̄||,头大了...

首先明确一个非常重要的点

线性表是一个线性结构,注意上篇博客提过线性结构是数据的逻辑结构中的一种

基本概念

线性表是由n(n≥0)个数据元素组成的有穷序列

大白话:在内存上一个个排着,找到一个,剩下的挨着找就行

数据元素又称作结点

吐槽:人类在创造术语的路上就是这么带劲,上节课刚说数据元素又称元素,这又来一个结点,得,记住吧

结点个数叫做表长,那么我们用一张完整的图来说明一下

ada52e39f1beb67dcbb7577f21dfc0a6.png

线性表的基本运算,需要了解一下

  1. 初始化 Initiate(L)
  2. 求表长 Length(L)
  3. 读表元素 Get(L,i)
  4. 定位 Locate(L,i)
  5. 插入Insert(L,x,i)
  6. 删除Delete(L,i)

线性表的顺序存储

用顺序存储实现的线性表称为顺序表。一般使用数组来表示顺序表

接下就是刺激的时刻了,比较难的部分来了,因为要用C来实现线性表的基本运算

首先假定线性表的数据元素的类型为DataType ,这个DataType 可以是自定义的,也可以是默认的int,char等类型

const int Maxsize = 100 ;  // 预先定义一个足够大的常数
typedef struct{DataType data[Maxsize]; // 存放数据的数组int length ; // 顺序表的实际长度
} SeqList; // 顺序表类型名为SeqList  
SeqList L ;  // 定义一个L为顺序表

实现插入操作,函数名字为InsertSeqList(SeqList L,DataType x,int i) 表示在顺序表第i(1≤i≤n+1)个元素之前,插入一个新元素。使得线性表长度加1。

上面是逻辑上的C语言实现,接下来咱们先引用一个图,说明一下如何用C语言在内存上开辟一块空间,并且向里面存数据

#include <stdio.h>
#include <stdlib.h>const int Maxsize = 10;
typedef struct SeqList{int *data; //一个int指针,后面用来初始化数组用int length;
} seq;// 顺序表的初始化函数
seq init(){seq s;s.data = (int*)malloc(Maxsize*sizeof(int)); // 构造一个空的顺序表,动态申请存储空间if(!s.data) // 如果申请失败,退出程序{printf("初始化失败");exit(0);}s.length = 0; // 空表的长度初始化为0return s;
}

上述代码,相当于在内存上做了图示的操作

80d57f22bf39b10e645c40f07713cee2.gif

开辟空间之后,向每个小格子里面添加数字

void display(seq s){for(int i=0;i<s.length;i++){printf("%d",s.data[i]);}printf("n");}int main()
{seq s = init();//添加一个元素进入for(int i=1;i<=5;i++){s.data[i-1] = i;s.length++;}printf("初始化之后,表的数据为:n");display(s);return 0;
}

可以看动画理解

873fda761ce7923a610a0a3f5a137592.gif

添加元素完成之后,就是删除元素

删除的基本步骤 1. 结点a~i+1~,....a~n~依次向左移动一个元素位置 2. 表长度减1

看一下代码吧

seq delete_seq(seq s,int i){if(i<1||i>s.length){printf("位置错误");exit(0);}// 第i个元素下标修改为i-1for(int j=i;j<s.length;j++){s.data[j-1] = s.data[j];}s.length--;return s;
}

接下来实现定位的算法,说白了,就是判断一个值(x)的位置(i)

C语言的代码如下

// 注意,这个地方需要返回的为int了,也就是位置
int locate(seq s,int x){int i =0;while((i<s.length)&&(s.data[i]!=x)){i++;}if(i<s.length) return i+1;else return -1;
}

线性表的顺序存储的时间复杂度

|运算| 插入|删除|定位|求表长|读取元素| |--|--|--|--|--|--| | 时间复杂度|O(n) |O(n)|O(n)|O(1)|O(1)| 具体是怎么来的,需要你自己看看算法的实现喽,通过上述表格知道 顺序表的插入、删除算法在时间性能方面不是很理想,接下来我们就采用线性表的链接存储来看一下,是否存在优化。

线性表的链接存储

链式存储结构,上来需要记住有三种常见的 单链表循环链表双向循环链表

首先明确,单链表中每个结点由两部分组成

00f6cda16ef9f20ea9d8df190108a240.png

- data表示==数据域== - next表示==指针域==或==链域==

一些简单的结点概念

0acc1987f3ad22f93ba689b2bba615b1.png

线性表在单链表上实现基本运算

接下来重头戏来了,我们要用代码实现一个简单的单链表

空的单链表由一个头指针和一个头结点组成

初始化

初始化之前,我们需要先用C语言定义一个新的结构体

//链表中的每个结点的实现
//包含数据域与指针域
typedef struct node{int data;// 数据域,为了计算方便,类型设置为数字struct node *next; // 指针域,指向后继元素
} Node,*LinkList;

结构体定义好了之后,就可以开始初始化操作了 头结点初始化其实就是在内存上开辟一块空间,然后将指针域指向NULL

5c414e3d33f63c7a1c59914812840103.png

请看代码,注意返回的是一个指针类型,说白了就是头结点的地址

// 初始化
LinkList init(){Node *L; // 定义一个头结点L =(LinkList)malloc(sizeof(Node)); //头结点申请地址if(L == NULL){printf("初始化失败!n");exit(0);}L->next =NULL;return L;
}

初始化成功,开始插入元素

插入元素,有头插入、尾插、任意插

先说一下头插,当头结点初始化完毕之后,第一个元素插入进来就比较简单了,看动图 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191110174036251.gif =400x) 这是插入一个元素,在用头插法插入第二个元素呢? ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191110174900608.gif =500x) 新生成的pnew2首先将自己的指针域指向头结点的指针域pnew2->next = L.next,然后L.next = pnew2 即可

上述的逻辑写成代码如下

// 头插入法
void insert_head(Node *L){int i,n,num;  // n表示元素的个数 Node *pnew;printf("请输入要插入的元素个数:n = ");scanf("%d",&n);for(i=0;i<n;i++){printf("请输入第%d个元素: ",i+1);scanf("%d",&num);pnew = (LinkList)malloc(sizeof(Node));pnew->data = num; // 将数字存储到数据域pnew->next = L->next; // 指针域指向L(头结点)的指针域L->next = pnew; // 头结点指针域指向新结点地址}
}

接下来看一下尾插法,其实理解起来也不难,说白了就是在链表后面追加元素即可 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191110180601505.gif =600x) 代码如下,这个地方看一下里面有一个p=L请问直接使用L可以吗?为什么不直接用,搞清楚了,你也就明白了

// 尾插法
void insert_tail(Node *L){int i,n,num;Node *p,*pnew;p = L;printf("要输入元素的个数:n = ");scanf("%d",&n);for(i=0;i<n;i++){printf("请输入第%d个元素:",i+1);scanf("%d",&num);pnew = (LinkList)malloc(sizeof(Node));if(pnew == NULL){printf("初始化失败");exit(0);}pnew->data = num;p->next = pnew;p = pnew;}p->next = NULL;}

剩下的算法实现就比较简单了,例如求表长,通过循环的方式,计算一下即可

//求表长
int get_length(LinkList L){LinkList p;int length = 0;p = L->next;   // p 指向第一个结点while(p){printf("单链表的数据为%dn",p->data);length++;p = p->next;}return length;
}

读表中的元素

// 读表中的元素
LinkList get_element(LinkList L,int i){// 在单链表L中查找第i个结点,若找到,则返回指向该结点的指针,否则返回NULLNode *p;p = L->next;int position = 1;while((position<i)&&(p!=NULL)){ // 当未到第i结点且未到尾结点时继续后移p = p->next;position++;}if(i==position) return p; //找到第i个结点else return NULL;   // 查找失败
}

读取表的元素,还可以按照值去找,返回位置,尝试一下吧,写起来都是比较容易的

int get_element_by_data(LinkList L,int x){Node *p;p = L->next;int i = 0;while(p!=NULL && p->data == x){p = p->next;i++;}if (p!=NULL) return i+1;else return 0;
}

写个复杂点的,在任意位置插入一个元素,这个还是好玩一些的

/在任意位置插入元素,x为要插入的内容,i为插入的位置
void insert(LinkList L,int x,int i){Node *p,*q; //p表示要插入的元素,q表示要被插入的元素if(i==1) q = L; //如果i==1,那么p=L进行初始化操作else q = get_element(L,i-1); // 找到第i-1个元素if(q==NULL){printf("找不到位置");exit(0);}else{p =(LinkList)malloc(sizeof(Node));p->data = x;p->next = q->next; // 新生成的p指向q的下一个结点q->next = p;//q的指针域指向新生成的p}
}

简单说明一下吧 大白话为 要在第i个位置插入一个元素x,那么需要找到i-1位置的元素,这个元素叫做 q

让新元素p(数据域为x,指针域为空)的指针域指向第i 元素,也就是q原先的指针域,==防止丢失掉==

然后在叫q的指针域指向p的地址即可,如果还不明白,看图

5408fd139d527ecc394b48b2e471ec45.png

对于删除任意位置的节点,这个就要留给你自己了

如果将a~i~移除链表,需要找到直接前驱,让直接前驱的指针域指向a~i+1~的地址就可以了

记得,通过free(p)释放结点

删除全部结点也需要自己完成一下,尽量把代码写完哦~~~

单链表的时间复杂度

  • insert(LinkList L,int x,int i) 时间复杂度为O(n^2^)
  • 头插法和尾插法时间复杂度为O(n)

循环链表

环状链表只需要将表中最后一个结点的指针指向头结点,链表就形成了一个环 如图

6bc2f767124442b2d13946764013aa81.png

循环链表如何想研究一下可以去实现约瑟夫环,由于本教材中不是重点,所以选修即可

双向循环链表

双向循环链表就是在单链表中的每个结点在增加一个指向直接前驱的指针域prior ,这样每个结点就有两个指针了

66b5a652f346e8a52f13b5945bb1b0b7.png

注意点 1. 双向循环链表是一种对称结构,即可以直接访问前驱结点又可以直接访问后继结点,所以找前驱和后继结点的时间复杂度都是O(1),也可以得到结论双向循环链表适合应用在需要经常查找结点的前驱和后继场合 2. p = p->prior->next = p->next->prior

教材中重点给出了删除和插入的两个逻辑,我们看一下

// p表示的是待删除的结点
p->prior->next = p->next;
p->next->prior = p->prior;
free(p)

图示如下

c3defce9f12a3214656b876d0aad87e8.png

大白话 先让p等于要删除的结点,然后把p删除前,需要将p的前驱和后继结点连接起来,刚才的代码干的就是这个事情!

插入逻辑

在p所指的结点后面插入一个新结点*t,需要修改四个指针:
t->prior = p;
p->next = t;  // 这两个步骤将t和p连接起来了t->next = p->next;
p->next->prior = t; //这两个步骤将t和p后继结点连接起来了

期末考试

这章是期末考试或者自考的一个比较重要的考试章节,一般会出现算法设计题,难度系数挺高的

建议,在能力范围内用C语言实现顺序表的基本运算,实现单链表的基本运算

懵了吧,嘿嘿~,多看几遍,多看几遍,看图,看图,写代码,运行,运行

欢迎关注,梦想橡皮擦公众号哦~

6de2c87e9a8bd065fa7b2d89dccb7bde.png

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

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

相关文章

TYVJ P1012 火柴棒等式 Label:枚举

背景 NOIP2008年提高组第二题描述 给你n根火柴棍&#xff0c;你可以拼出多少个形如“ABC”的等式&#xff1f;等式中的A、B、C是用火柴棍拼出的整数&#xff08;若该数非零&#xff0c;则最高位不能是0&#xff09;。用火柴棍拼数字0-9的拼法如图所示&#xff1a;注意&#xff…

python怎么开发软件_怎么使用python进行软件开发

一、下载pyinstaller 我使用的版本为PyInstaller-2.1&#xff0c;支持python版本2.3-2.7&#xff0c;点击这里下载。 二、安装pyinstaller 下载完成后&#xff0c;解压即可。我的解压目录为D:\Python27\PyInstaller-2.1\ 三、使用pyinstaller打包.py成.exe应用程序 1.注意使用前…

28、清华大学脑机接口实验组SSVEP数据集:通过视觉触发BCI[飞一般的赶脚!]

前言&#xff1a; 哈喽&#xff0c;最近对清华大学脑机接口的数据进行了尝试&#xff0c;输入到了DL模型中&#xff0c;以下是本人对于清华BCI数据的个人见解。 数据地址&#xff1a; 清华大学脑机接口研究组 (tsinghua.edu.cn) 打开网站可以看到有很多个数据&#xff0c;官…

python Pexpect

http://www.cnblogs.com/dkblog/archive/2013/03/20/2970738.htmlhttp://www.ibm.com/developerworks/cn/linux/l-cn-pexpect2/index.htmlhttp://www.cnblogs.com/dkblog/archive/2013/03/20/2970738.htmlpython Pexpect Pexpect 是一个用来启动子程序并对其进行自动控制的纯 P…

3dmax镜像后模型线条乱了_3dMax入门教程来啦!小白赶紧收藏!

3D Studio Max&#xff0c;常简称为3d Max或3ds MAX&#xff0c;是Discreet公司开发的&#xff08;后被Autodesk公司合并&#xff09;基于PC系统的三维动画渲染和制作软件&#xff0c; 3dmax软件主要功能有建模&#xff0c;动画&#xff0c;渲染&#xff0c;特效等&#xff0c;…

如何将多个一维列表转化为二维列表_数据分析2_如何处理一维、二维数据

吞一块大饼&#xff0c;还不如切成小块吃得香常见的数据集&#xff0c;要么是数列&#xff0c;要么是表格&#xff1b;因此&#xff0c;数据分析最首要的是&#xff0c;处理一维、二维数据。主要知识点可参考如图。如需要&#xff0c;可点击以下百度网盘链接下载数据分析基础知…

关于java中锁的面试题_Java面试题-Java中的锁

1. 如何实现乐观锁(CAS)&#xff1f;如何避免ABA问题&#xff1f;答&#xff1a;1)读取内存值的方式实现了乐观锁(比如&#xff1a;SVN系统)&#xff0c;方法&#xff1a;第一&#xff0c;比较内存值和期望值&#xff1b;第二&#xff0c;替换内存值为要替换值。2)带参数版本来…

NSUserDefaults

2019独角兽企业重金招聘Python工程师标准>>> NSUserDefaults 转载于:https://my.oschina.net/18829297883/blog/737931

什么是算术运算和逻辑运算_8086微处理器的算术和逻辑运算

什么是算术运算和逻辑运算逻辑指令 (Logical Instructions) a) AND: Logical AND a)AND&#xff1a;逻辑AND Atleast one of the operant should be a register or a memory operant both the operant cannot be a memory location or immediate operant. 操作中的至少一个应该…

h5引入json_Vue中如何使用本地Json文件?

我需要将菜单配置成Json文件&#xff0c;然后再程序中引入{{menu.name}}import menuListConfig from ../../config/menu.jsonexport default {name: "Sider",data(){return {menuList:JSON.parse(JSON.stringify(menuListConfig))}}}需要如何做&#xff0c;才能v-for…

python2和python3的默认编码_python2和python3哪个版本新

Python2 还是 Python3 &#xff1f; py2.7是2.x系列的最后一个版本&#xff0c;已经停止开发&#xff0c;不再增加新功能。2020年终止支持。 所有的最新的标准库的更新改进&#xff0c;只会在3.x的版本里出现。Python3.0在2008年就发布出来&#xff0c;而2.7作为2.X的最终版本并…

使用python套用excel模板_Python自动化办公Excel-从表中批量复制粘贴数据到新表

1、模块安装 1&#xff09;cmd模式下&#xff1a; pip install -i https://pypi.tuna.tsinghua.edu.cn/simple xlrd pip install -i https://pypi.tuna.tsinghua.edu.cn/simple openpyxl 2&#xff09;如果有安装Pycharm&#xff0c;则在程序中操作如下&#xff1a; 菜单栏&…

在HubSpot是如何应对Fat JAR困境的

在七月底&#xff0c;Spring Boot和Dropwizard分别发布了1.4和1.0版本&#xff0c;它们都是基于Fat JAR的。随着人们更多地采用这些框架和微服务架构&#xff0c;Fat JAR成为了通用的部署机制。\\Fat JAR技术会将Java应用的所有依赖打包到一个bundle之中&#xff0c;便于执行&a…

如何查看本地的崩溃log_过年回家,还怕抢不到票?程序员教你如何抢票

2019年接近尾声&#xff0c;距离春节回家的日子越来越近&#xff0c;26日起&#xff0c;2020年除夕火车票正式开售&#xff0c;抢票大战也进入白热化阶段。是否为某抢票 App 加速而烦恼&#xff0c;是否为车票“秒光而烦恼”。别慌&#xff0c;作为连“对象”都是 new 出来的程…

hashmap转红黑树的阈值为8_面试必考的 HashMap,这篇总结到位了

点击蓝色“JavaKeeper”关注我哟加个“星标”&#xff0c;一起成长&#xff0c;做牛逼闪闪的技术人1 概述HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长.HashMap是非线程安全的,只适用于单线程环…

Failed to start firewalld.service: Unit firewalld.service is masked.

2019独角兽企业重金招聘Python工程师标准>>> FireWall in Centos 7 masked How to resolve the error message belowFailed to issue method call: Unit firewalld.service is masked. The main reason a service is masked is to prevent accidental starting or e…

mysql第二个索引_MySQL高级第二章——索引优化分析

一、SQL性能下降原因1.等待时间长&#xff1f;执行时间长&#xff1f;可能原因&#xff1a;查询语句写的不行索引失效(单值索引、复合索引)CREATE INDEX index_user_name ON user(name);(底层做了一个排序)CREATE INDEX index_user_nameEmail ON user(name,email);查询关联join…

西瓜仿站高手v1.08官方正式版

2019独角兽企业重金招聘Python工程师标准>>> 西瓜仿站高手是一款绿色好用的由追风网络出品的网站模板批量下载软件&#xff0c;西瓜仿站高手是一款仿站工具&#xff0c;仿站神器。软件功能强大&#xff0c;能够帮你轻松帮你下载任意网站、任意模板&#xff0c;并且速…

用hundred造句子_八个有趣的开学破冰游戏,线上线下都能用

知道大家最近都很忙&#xff0c;所以省略开篇&#xff0c;直接上正题——开学“破冰游戏”走起&#xff01;一、你比划我来猜把词语展示在PPT上&#xff0c;猜词的同学背对PPT&#xff0c;其他同学可以看到词语并且用身体动作把词语表现出来&#xff0c;直到猜词的同学可以把词…

cisco packet tracer路由器配置_【干货】思科交换机路由器怎么配置密码?

今天带大家看看如何在思科的交换机路由器当中配置安全特性&#xff0c;也就是密码的配置方式。在学习配置之前&#xff0c;我们先回顾一下密码相关知识。密码学是研究信息系统安全保密的科学。人类有记载的通信密码始于公元前400年&#xff0c;古希腊人是置换密码学的发明者。密…