逻辑结构上呈线性分布的数据元素在实际的物理存储结构中也同样相互之间紧挨着,这种存储结构称为线性表的顺序存储结构。
也就是说,逻辑上具有线性关系的数据按照前后的次序全部存储在一整块连续的内存空间中,之间不存在空隙,这样的存储结构称为顺序存储结构。
使用顺序存储结构存储的数据,第一个元素所在的地址就是这块存储空间的首地址。通过首地址,可以轻松访问到存储的所有的数据,只要首地址不丢,数据永远都能找着(一根绳上的蚂蚱,要有就都有)。
使用线性表的顺序存储结构生成的表,称为顺序表。
图1 顺序表结构示意图
顺序表的实现方法
顺序表中存放数据的特点和数组这种数据类型完全吻合,所以顺序表的实现使用的是数组。
数组实现顺序表的存储结构时,一定要注意预先申请足够大的内存空间,避免因存储空间不足,造成数据溢出,导致不必要的程序错误甚至崩溃。
顺序表的存储结构
在建立顺序表时,除了预先申请内存空间,还需要实时记录顺序表的长度和顺序表本身申请的内存大小,便于后期对顺序表中的数据元素进行调取。
代码实例:
package main
import (
"errors"
"fmt"
)
type ElemType int //元素类型
const MAXSIZE = 20 //申请内存大小
//定义数据元素:结构体作为数据元素,内存包括存放数据的数组、数据的长度
type SqList struct {
data [MAXSIZE] ElemType
length int
}
//获取数据元素
func GetElem(s SqList, i int) (err error, res ElemType) {
//查找的线性表为空 下标越界(小于0或者大于长度值)
if s.length == 0 || i < 0 || i > s.length {
//return errors.New("查找失败")
err = errors.New("查找失败")
}
//*e = s.data[i]
res = s.data[i]
return
}
//插入数据
func ListInsert(s *SqList, i int, e *ElemType) error {
if s.length == MAXSIZE {
return errors.New("线性表已满,不能插入数据")
}
if i < 0 || i > s.length {
return errors.New("插入的位置不正确")
}
//i位开始后移一位
for j := s.length; j >= i; j-- {
s.data[j+1] = s.data[j]
}
s.data[i] = *e
s.length++
return nil
}
//删除数据
func ListDelete(s *SqList, i int) (err error) {
if s.length == 0 {
//return errors.New("线性表为空")
err = errors.New("线性表为空")
}
if i < 0 || i > s.length-1 {
//return errors.New("删除的位置不正确")
err = errors.New("删除的位置不正确")
}
//*e=s.data[i]
for j := i; j < s.length-1; j++ {
s.data[j] = s.data[j+1]
}
s.data[s.length-1] = 0 //清除数据
s.length--
return
}
func main() {
//添加数据
var s SqList
var result ElemType = 10
ListInsert(&s, 0, &result)
result = 20
ListInsert(&s, 1, &result)
result = 30
ListInsert(&s, 2, &result)
result = 40
err := ListInsert(&s, 3, &result)
fmt.Println("添加数据")
if err != nil {
fmt.Println(err)
} else {
//fmt.Println(result)
fmt.Println(s)
}
//获取数据元素(查找数据元素)
_, res := GetElem(s, 1)
fmt.Println(res)
//删除数据元素
err = ListDelete(&s, 1)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(s)
}
}