数据结构和算法基础–线性表
数据结构 = 数据的逻辑结构+数据的存储结构+数据的运算
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-28ek7MfI-1642426292721)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211215231756058.png)]
线性表的定义和特点
线性表是具有相同特性的数据元素的一个有限序列
(a1,a2,a3,a4,a5,a6,a7,a8,…an)
a1线性起点(起始节点)
每个数据元素都有一个直接前趋和一个直接后继
an线性结点(终端节点)
线性表(Linear List)
由n(n>=0)个数据元素(结点)a1, a2, a3, …an组成的有限序列
- 其中数据元素的个数n定义为表的长度
- 当n=0时候称为空表
- 将非空的线性表(n>0)记作(a1,a2,a3,…an)
- 这里的数据元素ai(1<=i<=n)只是一个抽象的符号,其具体含义在不同的情况下可以不同。
同一线性表中的元素必定具有相同特性,数据元素间的关系是线性关系
线性表的逻辑特征是
线性表是一种典型的线性结构。
-
在非空的线性表,有且仅有一个开始节点a1,他没有直接前,而仅有一个直接后继a2
-
有且仅有一个终端节点an,他没有直接后继,二仅有一个直接前驱an-1
-
其余的内部节点ai(2<=I<=N-1)都有且仅有一个直接前趋ai-1和一个直接后继ai+1
-
线性表中的数据元素可以为简单类型,也可以为复杂类型(比如记录)
-
许多实际应用问题所涉及的基本操作有很大相似性,不应为每个具体应用单独编写一个程序。
-
从具体应用抽象出共性的逻辑结构和基本操作(抽象数据类型),然后实现其存储结构和基本操作
顺序存储结构存在问题
- 存储空间分配不灵活
- 运算的的空间复杂度高
链式存储结构
线性表的顺序表示和实现
存储结构
- 顺序存储结构
- 链式存储结构
线性表的顺序表示又称为顺序存储结构或者顺序映像
**顺序存储定义:**把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构
简言之,逻辑上相邻物理上也相邻
线性表的第一个数据元素a1的存储位置,称为线性表的起始位置或基地址,线性表顺序存储结构占用一片连续的存储空间。知道某个元素的存储位置就可以计算其他元素的存储位置(好处)
假设线性表的每个元素占L个存储单元,则第i+1个数据元素的存储位置和第i个数据元素的存储位置之间满足关系
LOC(ai+1)=LOC(ai)+L
与高级语言对比
顺序表(元素) = [地址连续, 依次存放, 随机存取, 类型相同] ≈ 数组(元素)
所以可以用一个一维数组表示顺序表,在go中准确的应该是切片
但是
-
线性表可变(删除)
-
数组长度不可动态定义
go var arr01 := [...]int {1,2,3,4}
线性表的顺序存储表示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LT8CrfJT-1642426292724)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211221080722879.png)]
顺序表的插入
插入位置在最后
package main
import "fmt"
func main() {
//插入位置在最后
arr01 := []int{1, 2, 3, 4, 5, 6} //切片
arr01 = append(arr01, 7)
fmt.Println(arr01)
}
-----
[1 2 3 4 5 6 7]
插入位置在中间
package main
import "fmt"
// 插入位置在中间
func insertArray(a []int, target int, index int) []int {
switch {
case index > len(a):
panic("index out of array length")
case index < 0:
panic("index must Positive integer")
}
new_a := []int{}
for k, v := range a {
if k == index {
new_a = append(new_a, target)
}
new_a = append(new_a, v)
}
return new_a
}
func main() {
//插入位置在最后
arr01 := []int{1, 2, 3, 4, 5, 6}
arr01 = append(arr01, 7)
fmt.Println(arr01)
new_a := insertArray(arr01, 99, 1)
fmt.Println(new_a)
}
顺序表的特点
以物理位置相邻表示逻辑关系
顺序表优点
任意元素均可随机存取
顺序表的缺点
进行插入和删除操作时需要移动大量的元素。存储空间不灵活
线性表的链式表示和实现
- 链式存储结构
- 结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻
- 线性表的链式表示又称为非顺序映像或链式映像
- 用一组 物理位置任意位置的存储单元来存放线性表的数据元素。
- 这组存储单元既可以是连续的也可以是不连续的,甚至是零散分布在内存中的任意位置上的
- 链表中元素的逻辑次序和物理次序不一定相同
与链式存储有关的术语
- 结点:数据元素的存储映像。由数据域和指针域两部分组成
- 链表:n个结点由指针链组成一个链表,他是线性表的链式存储映像,称为线性表的链式存储结构
链表的类型
单链表:
结点只有一个指针域的链表,称为单链表或线性链表
双链表
结点有两个指针域的链表,称为双链表
循环链表
首位相接的链表称为循环链表
头指针、头节点和首元结点:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ll2kulfV-1642426292726)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211223222759344.png)]
头指针:是指向链表中第一个结点的指针
头节点:实在链表的首元结点之前附设的一个结点
首元结点:是指链表中存储第一个元素a1的结点
不带头结点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BdW32t9s-1642426292728)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211223222950658.png)]
头指针直接存放第一个元素地址
空表:头指针为空时表示空表
带头结点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fOT9Ucko-1642426292729)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211223223059083.png)]
头节点的指针域再来存放首元结点
空表:当头节点的指针域为空是为空表
好处
- 便于首元节点的处理
- 首元节点的地址保存在头节点的指针域中,所以在链表的第一个位置上的操作和其他位置一致,无须进行特殊处理
- 便于空表和非空白的统一处理
- 无论链表是否为空,头指针都是指向头结点的非空指针,因此空表和非空表的处理也就统一了。
头节点数据域可以为空也可以存放线性表长度等附加信息,但此节点不能计入链表长度
链表的特点
-
结点在存储器中的位置是任意的,j即逻辑上相邻的数据元素在物理上不一定相邻。
-
访问时只能通过头指针进入链表,并通过每个节点的指针域依次向后顺序扫描其余节点,所以寻找第一个节点和最后一个结点所花费的时间不等
这种存取元素的方法被称为顺序存取法(顺序表是随机存取(O1)链表是顺序存取(O))
就统一了。
头节点数据域可以为空也可以存放线性表长度等附加信息,但此节点不能计入链表长度
链表的特点
-
结点在存储器中的位置是任意的,j即逻辑上相邻的数据元素在物理上不一定相邻。
-
访问时只能通过头指针进入链表,并通过每个节点的指针域依次向后顺序扫描其余节点,所以寻找第一个节点和最后一个结点所花费的时间不等
这种存取元素的方法被称为顺序存取法(顺序表是随机存取(O1)链表是顺序存取(O))