c语言数据结构,你可能还不知道的顺序表
数据结构顺序表
顺序表定义
1,前言
线性表的顺序存储又称为顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。其最大的特点就是:元素的逻辑顺序与其物理顺序相同。
线性表的顺序存储结构中任一元素都可以随机存取,并且注意:线性表中元素的位序是从1 开始的,而数组中元素的下标是从0 开始的。假定线性表的元素类型为 EleType ,则线性表的顺序存储类型可以描述为:
#define MaxSize 50 //定义线性表的最大长度
typedef struct {
ElemType data[MaxSize]; //顺序表的元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义
2,动态实现
1,结构定义:
#define InitSize 10 //默认的最大长度
typedef struct{
int *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
}SeqList;
2,初始化顺序表:
void InitList(SeqList &L){
//用malloc函数申请一片连续的存储空间
L.data=(int *)malloc(InitSize*sizeof(int));
L.length=0;
L.MaxSize=InitSize;
}
3,增加动态数组的长度:
void IncreaseSize(SeqList &L,int len){
int *p=L.data;
L.data=(int *)malloc((L.MaxSize+len)*sizeof(int));
for(int i=0;i<L.length;i++)
L.data[i]=p[i]; //将数据复制到新区域,时间开销很大
L.MaxSize=L.MaxSize+len; //顺序表最大长度增加len
free(p); //释放原来的内存空间
}
顺序表上的基本操作
1,插入操作(Listsert(&L,i,e)
在表L 中的第i 个位置上插入指定元素e 。以下采用的是“静态分配的方式实现。
以下给出实现的主要代码部分,便于我们阅读理解:
#define MaxSize 10 //定义线性表的最大长度
typedef struct {
int data[MaxSize]; //用静态的“数组”存放数据元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义
bool ListInsert(Sqlist &L,int i,int e){
if(i<1||i>L.length+1)
return false;
if(L.length>=MaxSize) //当前存储空间已满,不能插入
return false;
for(int j=L.length;j>=i;j--) //将第i个元素及其后的元素后移
L.data[j]=L.data[j-1];
L.data[i-1]=e; //在位置i处放入e
L.length++; //线性表的长度加1
return true;
int main(){
SqList L; //声明一个顺序表
InitList(L); //初始化顺序表
//...此处省略插入几个元素的代码
ListInsert(L,3,3);
return 0;
}
插入操作的时间复杂度分析:
通过观察以上代码,我们分析时间复杂度时只需要关注最深层循环语句的执行次数与问题规模n 的关系。即语句“L.data[j]=L.data[j-1];”即可:
- 最好情况:新元素插入到表位,不需要移动元素,i=n+1,循环0次;最好的时间复杂度为O(1)
- 最坏情况:新元素插入到表头,需要将原有的n 个元素全都向后移动,i =1,循环n 次;最坏的时间复杂度为O(n);
- 平均情况:假设新元素插入到任何一个位置的概率相同,概率为P=1/(n+1)。i=1,循环n 次;i =2 时,循环n-1次;i =3 ,循环n-2 次 ..... i =n+1 时,循环0 次。平均循环次数 =np+(n-1)p+(n-2)p+.....+1.p= n/2。即得平均时间复杂度= O(n)
提示:如果以上的分析i 的值和循环次数n 的关系不是太清楚,要回想下开头提到的线性表中元素的位序是从1 开始的,而数组中元素的下标是从0 开始的。
2,删除操作(ListDelete(SqList &L,int i,int &e))
删除顺序表L 中的第i (1<=i<=L.length)个位置的元素,用引用变量e 返回。若输入的i 不合法,则返回false ;否则,将被删元素赋给引用变量e ,并将第i+1 个元素及其后的所有元素一次往前移动一个位置,返回true 。
下面给出部分代码,辅助我们理解阅读:
bool ListDelete(SqList &L,int i,int &e){
if(i<1||i>L.length) //判断i的范围是否有效
return false;
e=L.data[i-1]; //将删除元素赋给引用变量e
for(int j=i;j<L.length;j++) //将第i个位置后的元素前移
L.data[j-1]=L.data[j];//这里再次提醒位序与数组下标的关系
L.length--; //线性表长度减1
return true;
}
int main(){
SqList L; //声明一个顺序表
InitList(L); //初始化
//.....省略一些代码
int e=-1; //用标量e将删除的变量“带回来”
if(ListDelete(L,3,3))
printf("已删除第3个元素,删除元素值为=%d\n",e);//试一下
else
printf("位序i不合法,删除失败\n");
return 0;
}
删除操作的是时间复杂度分析:
通过观察以上代码,我们分析时间复杂度时只需要关注最深层循环语句的执行次数与问题规模n 的关系。即语句“L.data[j-1]=L.data[j];”即可:
- 最好情况:删除元素,不需要移动其他元素,i=n,循环0次;最好的时间复杂度为O(1)
- 最坏情况:删除表头元素,需要将后续的n-1个元素全都向前移动。i=1,循环n-1次;最坏时间复杂度= O(n)
- 平均情况:假设删除任何一个元素的概率相同,及p=1/n,i=1,循环n-1次;i=2,循环n-2 次..... i=n 时,循环0次,故平均循环次数=(n-1)p+(n-2)p+.....+1.p=(n-1)/2.则时间复杂度为O(n)
3,按位查找(GetElem(L,i))
获取表L 中第i 个位置的元素的值。下面给出一段简单的代码示例:
#define InitSize 10 //顺序表的初始长度
typedef struct{
ElemType *data; //指示动态分配数组的指针
int MaxSize; //顺序表中的最大容量
int length; //顺序表的当前长度
}SeqList; //顺序表的类型的定义(动态分配方式)
ElemType GetElem(SeqList L,int i){
return L.data[i-1];
}
由于顺序表的各个元素在内存中连续存放,因此可以根据起始地址和数据元素大小立即找到第i 个元素,这也就是 随机存取特性的体现。因此其时间复杂度可得为 O(1)。
4,按值查找(LocateElem( L, e) )
在表L 中查找具有给定关键字的元素。如下给出在顺序表L 中查找第一个元素值等于e 的元素,并返回其位序:
int LocateElem(SeqList L,ElemType e){
for(int i=0;i<L.length;i++)
if(L.data[i]==e)
return i+1; //注意数组下标与顺序表位序的关系
return 0; //退出循环,说明查找失败
}
对于时间复杂度的分析:
通过观察以上代码,我们分析时间复杂度时只需要关注最深层循环语句的执行次数与问题规模n 的关系。即语句“ if(L.data[i]==e ”即可:
- 最好情况:目标元素在表头,循环1次;最好时间复杂度为O(1)
- 最坏情况:目标元素在表尾,循环n 次;最坏时间复杂度为O(n);
- 平均情况:假设目标元素出现在任何一个位置的概率相同,都是1/n,目标元素在第一位,循环1次;第2位,循环2次;....... 在第n 为,循环n 次,则平均循环次数 =1\n+2.1/n+....+n.1/n=(n+1)/2;则平均时间复杂度为O(n)。
关于顺序表的一些知识先就说这么多,共勉!
c语言数据结构,你可能还不知道的顺序表的更多相关文章
- [转载]或许您还不知道的八款Android开源游戏引擎
或许您还不知道的八款Android开源游戏引擎 分类: 技术文章 2010-08-04 20:27 17430人阅读 ...
- JS你可能还不知道的一些知识点(一)
js程序是用Unicode字符集编写的, 2.转义字符:反斜线 1 2 3 4 function Test(){ var s='you\'re right,it can\'t be a quote ...
- [数据结构]C#基于数组实现泛型顺序表
前方预警,只完成了顺序表的插入/删除/查找. 错误代码示例: /// <summary> /// 查找顺序表第i个位置的元素 /// 在显示情况中,我们更常用下标 /// </sum ...
- 或许您还不知道的八款Android开源游戏引擎
很多初学Android游戏开发的朋友,往往会显得有些无所适从,他们常常不知道该从何处入手,每当遇到自己无法解决的难题时,又往往会一边羡慕于iPhone下有诸如Cocos2d-iphone之类的免费游戏 ...
- jdk1.8新特性,还不知道的朋友还不看看,1.9都快出来了
一.接口的默认方法 Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,示例如下:代码如下:interface Formula { ...
- 你可能还不知道的关于JavaScript类型的细节?
类型 七种类型: Undefined Null Boolean String Number Symbol Object Undefined.Null 阅读问题:为什么有的编程规范要求使用void 0 ...
- 👊 Spring技术原理系列(7)带你看看那些可能你还不知道的Spring特性技巧哦!
前提介绍 本文主要介绍相关Spring框架的一些新特性问题机制,包含了一些特定注解方面的认识. @Lazy可以延迟依赖注入 @Lazy注解修饰在类层面! @Lazy @Service public c ...
- redis-cli中那些或许我们还不知道的一些实用小功能
玩过redis的朋友都知道,redis中有一个叫做redis-cli的小工具,我们可以利用它在test和develop环境下进行高效的模拟测试,然而在现实环境中, 我们只知道直接键入redis-cli ...
- html你可能还不知道的一些知识点
一.标签语义化 html标签语义化是让大家直观的认识标签和属性的用途和作用,好处最主要的是对搜索引擎友好. Eg: 1.如果你想在页面中突出"奥巴马"这三个字,让搜索引擎重视它,如 ...
随机推荐
- 初识python:tkinter 实现 弹球小游戏(非面相对象)
通过 tkinter 采用非面相对象式实现弹球小游戏(使用蹩脚式面相对象实现). #!/user/bin env python # author:Simple-Sir # time:2020/8/3 ...
- 初识python: 模块定义及调用
一.定义 模块:用来从逻辑上组织python代码(变量.函数.类.逻辑:实现一个功能),本质就是.py结尾的python文件(比如:文件名:test.py,对应的模块名:test) 包:用来从逻辑上组 ...
- Xshell 6 首次连接虚拟机 CentOS 7.6报错:/usr/bin/xauth: file /root/.Xauthority does not exist
使用 Xshell 6 首次连接虚拟机 CentOS 7.6 出现这样的提示: /usr/bin/xauth: file /root/.Xauthority does not exist 解决: 只需 ...
- 阿里云服务器ECS Ubuntu16.04 + Seafile 搭建私人网盘 (Seafile Pro)
原文链接:? 传送门 本文主要讲述 使用 Ubuntu 16.04 云服务器 通过脚本实现对 Seafile Pro 的安装,完成私人网盘的搭建 首先给出 Seafile 专业版的下载地址(Linux ...
- Java反射详解:入门+使用+原理+应用场景
反射非常强大和有用,现在市面上绝大部分框架(spring.mybatis.rocketmq等等)中都有反射的影子,反射机制在框架设计中占有举足轻重的作用. 所以,在你Java进阶的道路上,你需要掌握好 ...
- 【hexo指南】hexo配置ER图流程图时序图插件
偏技术的文章有时会用到各种图形,一般来说可以做好图然后截图放到文章中就好了,虽然但图片本身也很小,但存一大堆图片占用空间总觉得不是很好. mermaid mermaid官方网站 mermaid支持很多 ...
- [javaweb]strut2-001漏洞分析
Strut2-001 漏洞描述 框架解析JSP页面标签时会对用户输入的Value值获取,在获取对应的Value值中递归解析%{.}造成了二次解析,最终触发表达式注入漏洞,执行任意代码 影响版本 2.0 ...
- X-Y问题(X-Y problem)
X-Y Problem 什么是X-Y problem呢? 某人想要解决问题X 他认为Y可能是解决X问题的方法 但是他不知道Y怎么做 于是他去问别人Y应该怎么做 这就产生了一个X-Y problem 也 ...
- flask中错误使用flask.redirect('/path')导致的框架奇怪错误
我在首页的位置使用了如下代码: import flask @page_index.route('/') def index(): flask.redirect('/pythoncgi/') 结果站点出 ...
- 普罗米修斯+grafana监控k8s
其实现原理有点类似ELK.node-exporter组件负责收集节点上的metrics监控数据,并将数据推送给prometheus, prometheus负责存储这些数据,grafana将这些数据通过 ...