mysql 线性表_数据结构-线性表之顺序表

6a6ed80994543b31147619a0b3314ae6.png今天正式开工!开始总结数据结构这部分知识.

6958fa317411f738c95a2bf367fac80f.png

在正式总结前,我们梳理下数据结构的内容,算是绪论内容吧。

00

知识框架

c2a10b3cb498fae185ee3eecc9687154.png

在数据结构三要素中,我们主要梳理下数据的逻辑结构和物理结构。

【数据逻辑结构】

589f7616f5d50b1352d7c67fef5e4e98.png

逻辑结构是指数据元素之间的逻辑关系,即从逻辑关系上描述数据。它与数据的存储无关,是独立于计算机的。常见的数据逻辑结构分类如上图1.1。

集合   结构中的数据元素之间除了“同属于一个集合”的关系外,别无其他关系。

线性结构  结构中的数据元素之间只存在一对一的关系。

树形结构  结构中的数据元素之间存在一对多的关系。

图状结构或网状结构  结构中的数据元素之间存在多对多的关系。

【数据的存储结构】

存储结构是指数据结构在计算机中的表示(又称映像),也称物理结构。它包括数据元素的表示和关系的表示。数据的存储结构是逻辑结构用计算机语言的实现,它依赖于计算机语言。数据的存储结构主要有:顺序存储、链式存储、索引存储和散列存储。关于这些存储结构的定义请大家自行搜索理解。

【ADT】

抽象数据类型(ADT)是指一个数学模型以及定义在该模型上的一组操作,通常用(数据对象、数据关系、基本操作集)这样的三元组来表示抽象数据类型。因此可以用ADT定义一个完整的数据结构。

04465982bf66a56fa731c45c4d0ff00d.png

线性表

【知识框架】

1eec2803c44e1512601bdf4ce07a8152.png

01

理论知识

【线性表的定义】

90462c241ba61d080398fb4f60dd0588.png

【线性表的基本操作】

线性表的主要操作有:

79d505fb0e6d70055786651782c3baa8.png

【顺序表的定义】

线性表的顺序存储又称顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。第一个元素存储在线性表的起始位置,第i个元素的存储位置后面紧接着存储的是第i+1元素,称i为元素

04c89776333ee81ded6d61e8f53b08b3.png在线性表中的位序。因此,顺序表的特点是表中元素的逻辑顺序与其物理顺序相同。

b75a48aff7fb8395bef6ab053de39225.png

注意:线性表中元素的位序是从1开始的,而数组中元素的下表是从0开始

假定线性表的元素类型为ElemType,则线性表的顺序存储类型使用C语言描述为

#define MaxSize 50  //定义线性表的最大长度typedef struct{     ElemType data[MaxSize]; //顺序表的元素    int length; //顺序表的当前长度}SqList;     //顺序表的类型定义

一维位数组可以是静态分配的,也可以是动态分配的,在静态分配中由于数组大小和空间已定,一旦空间占满,再加入新的数据将会产生溢出,进而导致程序崩溃。

而在动态分配中,存储数组的空间是在程序执行过程中通过动态分配语句分配的,一旦数据空间占满,就另外开辟一块更大的存储空间,用以替换原来的存储空间,从而达到扩充存储数组空间的目的,而不需要为线性表一次性的划分所有空间。

#define InitSize 100 //表长度的初始定义typedef struct{    ElemType *data;   //指示动态分配数组的指针    int MaxSize,length;  //数组的最大容量和当前个数 } SeqList;       //动态分配数组顺序表的类型定义

C的初始动态分配语句为

L.data = (ElemType*)malloc(sizeof(ElemType)*InitSize);

C++的初始动态分配语句为

L.data = new ElemType[InitSize];

a1ddf2972acf3c172bf8d8819d2e1e8e.png

顺序表最主要的特点是 随机访问,即通过首地址和元素序号可在时间O(1)内找到指定的元素。顺序表的存储密度高,每个结点只存储数据元素。顺序表逻辑上相邻的元素物理上也相邻,所以插入和删除操作需要移动大量元素。

02

编程实现

考虑到自己日后以Go语言为主要工作语言,因此我会将所有的数据结构以Go语言改写,当然C/C++如何实现也是需要掌握的,理论知识暂且以C/C++进行总结。

package mainimport "fmt"// SqList  is a sqlist file//定义顺序表type SqList struct{//定义顺序表的最大长度maxSize int//定义当前顺序表的长度length int//顺序表的元素data []int}//InitSqList is to initmylist//初始化顺序表func InitSqList(InitSize int) *SqList{return &SqList{maxSize: InitSize, data: make([]int, InitSize)}}//IsEmpty is or not empty//检查顺表是否为空//方法是查看当前顺序表的长度是否为0func (mySqList *SqList) IsEmpty() bool{return mySqList.length == 0}//IsFull is or not full//判断当前顺序表长度是否已达到最大值func (mySqList *SqList) IsFull() bool{return mySqList.length == mySqList.maxSize}//ListInsert function is to insert an element//在i位置插入元素efunc (mySqList *SqList) ListInsert(i, e int) bool{if i < 1 || i > mySqList.length + 1 {fmt.Println("不合法,请检查i")return false}if i > mySqList.maxSize {fmt.Println("不合法,请检查i")return false}for j := mySqList.length; j >= i; j--{  //将第i个元素及之后的元素后移mySqList.data[j] = mySqList.data[j-1]}mySqList.data[i-1] = e    //在位置i处放入emySqList.length++        //线性表长度加1return true}//ListAppend function is to append an element//在尾部追加一个元素,需要和最大长度比较func (mySqList *SqList) ListAppend(e int) bool{if mySqList.IsFull() {fmt.Println("sorry list is maxsize")return false}mySqList.data[mySqList.length] = emySqList.length++return true}//ListDelete function is to remove en element//此方法是用来删除指定位置元素//method 1func (mySqList *SqList) ListDelete(i int) bool{if i < 1 || i > mySqList.length + 1 {fmt.Println("i不合法,请检查i")return false}if i > mySqList.maxSize {fmt.Println("i不合法,请检查i")}for j := i-1; j  mySqList.length + 1 {//     fmt.Println("i不合法,请检查i")//     return false//   }//   if i > mySqList.maxSize {//     fmt.Println("i不合法,请检查i")//   }//区别主要在这里,有两种思路//   for( j := i; j < mySqList.length; j++){//     mySqList.data[j-1] = mySqList.data[j]//   }//   mySqList.length--//   return true// }//ListFind function is to find an element//此方法用来查找指定位置的元素func (mySqList *SqList) ListFind(i int) bool{if i < 1 || i > mySqList.length + 1 {fmt.Println("i不合法,请检查i")return false}if i > mySqList.maxSize {fmt.Println("i不合法,请检查i")return false}fmt.Println(mySqList.data[i-1])return true}func main(){list := InitSqList(20)  //设置最大长度为20list.ListInsert(1,22)list.ListAppend(12)list.ListAppend(122)list.ListAppend(133)list.ListAppend(143)list.ListAppend(153)list.ListAppend(173)list.ListAppend(183)list.ListAppend(193)list.ListAppend(163)fmt.Println(&list)fmt.Println(*list)fmt.Println(*&list.length)list.ListDelete(5)//fmt.Println(*&list.data[2])fmt.Println(*list)list.ListFind(3)}

程序执行结果是

070c5855235bb3cdc5eca10c90595695.png

注意:区别顺序表的位序和数组下标。理解为什么判断插入位置是否合法时if语句中用length+1,而移动元素的for语句中只用length?

03

算法复杂度分析

【插入操作】

最好情况:在表尾插入(即i=n+1)元素后移语句将不执行,时间复杂度为O(1).

最坏情况:在表头插入(即i=1),元素后移语句将执行n次,时间复杂度为O(n).

平均情况:假设

48fe5d9f2c3fb1de3660760d27aedf65.png是在第i个位置上插入一个结点的概率,则在长度为n的线性表中插入一个结点时所需移动结点的平均次数为

a9fd3423b5e8ad299c236e90caaf0092.png

因此,线性表插入算法的平均时间复杂度为O(n).

【删除操作】

最好情况:删除表尾元素(即i=n)无需移动元素,时间复杂度为O(1).

最坏情况:删除表头元素(即i=1)需要移动除第一个元素外的所有元素,时间复杂度为O(n).

平均情况:假设

277454181835fee077a2673da39948b2.png是删除第i个位置上结点的概率,则在长度为n的线性表中删除一个结点时所需移动结点的平均次数为

f3d579d57b4063391b09b409f558b0ac.png

因此,线性表删除算法的平均时间复杂度为O(n).

【按值查找】顺序查找

最好情况:查找的元素就在表头,仅需比较一次,时间复杂度为O(1).

最坏情况:查找的元素在表尾(或不存在)时候,需要比较n次,时间复杂度为O(n).

平均情况:假设

b5128fad4d2cd6939ddb1d75d4691707.png是查找的元素在第i(1<=i<=L.length)个位置上的概率,则在长度为n的线性表中查找值为e的元素所需比较的平均次数为

c621617455ab283d67ffc75ee8b72d8a.png

因此,线性表按值查找算法的平均时间复杂度为O(n).

end

说明:考虑到时间成本,有些理论知识截图借鉴了部分计算机专业教材。还有考虑到一些数学符号问题,会逐渐使用LaTex命令进行排版。另外,由于每个部分知识点较多,故可能不会日更

2bc62d5c291a797da25b4a6ec912a715.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值