--------------------------------------------
线性表的定义
--------------------------------------------
通俗理解:
一个班级的小朋友,一个跟着一个排着队,有一个打头,有一个收尾,当中的的小朋友每一个都知道
他前面的一个是谁,他后面的一个是谁,这样如同一根线把他们串联起来了。就可以称之为线性表。
专业术语:
线性表(List):零个或多个数据元素值的有限序列
tag:一个序列、元素之间是有顺序的、有限的。
若元素存在多个,则第一个元素是无前驱,最一个元素无后继,其他元素都有且只有一个前驱和一个后继。
用数学语言来进行定义:
若将线性表记录(a1,...,a_i-1,a_i,a_i+1,...,a_n),则表中a_i-1领先于a_i,a_i, a_i领先于a_i-1,a_i-1是a_i的直接前驱元素,a_i+1是a_i的直接后继元素。
当i=1,2,...,n-1时,a_i有且仅有一个直接后继,当i=2,3,a_i有且仅有一个直接前驱。
所以线性元素的个数n(n<=0)定义为线性表的长度,当n=0时,称为空表。
--------------------------------------------
线性表的优点和缺点
--------------------------------------------
优点:
1.无需为表示中元素之间的逻辑而增加额外的存储空间
2.可以快速地取表中的任何一位置的元素
缺点:
1.插入和删除操作需要移动大量元素
2.当线性表长度变化较大时,难以确定存储空间的容量
3.造成存储空间的"碎片"
--------------------------------------------
线性表的抽象数据类型定义
--------------------------------------------
ADT 线性表(List)
Data
线性表的数据对象集合为{a_1,a_2,a_3,....,a_n},每个元素的类型均为DataType。其中,除第一个元素a_1外,
每一个元素有且只有一个直接前驱,除了最一个元素a_n外,每一个元素有且只有一个直接后继。数据元素之间的关系是
一对一的关系。
Operation
InitList(): 初如化操作,建立一个空的线性表L
ListEmpty(): 若线性表为空,返回true,否则返回false
ClearlList(): 将线性表清空
GetElem(i int) (bool,ElementType): 将线性表中第i位置的元素值返回
LocateElem(e ElementType) int :在线性表L中查找给定值e相等的元素,如果查询成功返回成功,返回该元素在线性表序号表示成功,否则,返回-1表示失败
ListInsertByPosition(i int,e ElementType) (bool,error):在线性表L中的第i个位置插入新元素e
ListDeleteForIndex(i int) ElementType:删除线性表中的第i个位置的元素,并用e返回其值
ListLength(): 返回线性表L的元素个数
endData
//线性表的顺序存储结构
线性表的顺序存储结构,指的是用一段连续的存储单元依次存储线性表的数据元素
我们这里使用一惟数组来实现顺序存储结构,即把第一个数据元素存到数组下标0的位置。接着把线性表相邻的元素存储在数组中相邻的位置。
package main
import(
"errors"
"fmt"
)
const MAXSIZE = 6 //存储空间初始分配容量
type ElementType int //*ElementType类型根据实际情况而定,这里假设为为*int
var data [MAXSIZE]ElementType // //数组存储数据元素,最大值为MAXSIZE
var length int //线性表当前长度
//初如化操作
func InitList(){
data = [MAXSIZE]ElementType{} //数组存储数据元素,最大值为MAXSIZE
length = 0 //线性表当前长度
}
/**
数组的长度与线性表长度的区别
数组的长度是存入线性表的存储空间的度,存储分配最后这个最一般是不变的。
线性表的长度是线性表中的数据元素的个数,随着线性表插入和删除操作的进行,这个量是变化的
在任意时刻,线性表的长度应该小于数组的长度
地址计算方法:
存储器中的每个存储单元都有自己的编号,这个编号称为地址。
由于每个数据元素,不管它是整型,实型还是字符,它都是需要占用一定的存储单元空间的。
假设占用的是c个存储单元,那第线性中第i+1个数据元素的存储位置和第i个数据元素的存储位置满足下列关系
(LOC表示获得存储位置的函数)
LOC(a_i+1)=LOC(LOC(a_i))+c
所以对第i个数据元素a_i的存储位置可以由a1推算得出:
LOC(a_i)=LOC(a_1)+(i-1)*c
*/
//顺序存储结构的插入与删除
/**
* 获取第i个元素
* GetElem(L,i,*e): 将线性表中第i位置的元素值返回给e 翻译go代码 func GetElem(i int) (bool,*ElementType)
* return bool //true 返回元素成功获取,false表示获取失败
* return *ElementType //不存在则返回nil
*/
func GetElem(i int) (bool,ElementType){
if i < 0 || i > len(data){
return false,-1
}
return true, data[i-1]
}
/**
*查询指定元素所在位置索引
*/
func LocateElem(e ElementType) int{
for i,v := range data{
if v == e {
return i
}
}
return - 1
}
/*
插入元素
ListInsert(*L) 翻译成go代码 func InitList(e ElementType)(bool,error)
*/
func ListInsert(e ElementType) (bool,error) {
if length == len(data){ //顺序线性表已经满,返回false表示插入失败
return false,errors.New(fmt.Sprintf("存储空间已满,无法插入元素:%v",e))
}
data[length] = e
length++ //计数加1
return true,nil
}
/**
1. 如果插入位置不合理,排除异常
2. 如果线性表长度大于等数组长度,则排除异常或动态增加容量
3. 将指定位置的数据向后移动,并将新的数据插入当前位置
4. 长度增加1
*/
func ListInsertByPosition(i int,e ElementType) (bool,error){
if length == len(data) {
return false,errors.New("线性表空间已经满,无法插入新的数据元素")
}
if i < 0 || i > len(data){
return false,errors.New(fmt.Sprintf("索引越界"))
}
for k := length -1; k >= i - 1; k--{
data[k+1] = data[k]
}
data[i-1] = e
length++
return true,nil
}
/**
*删除指定元素
*/
func ListDelete(e ElementType) bool {
//获取该数据元素的索引位置
var index int = LocateElem(e)
if index >=0{
for k := index; k < length; k++{
if k == length -1{
data[k] = 0
}else {
data[k] = data[k+1]
}
}
length--
return true
}
return false
}
/**
*删除指定位置的元素
*/
func ListDeleteForIndex(i int) ElementType {
i = i - 1
if i < 0 || i >= length {
return -1
}
var value ElementType = data[i]
if i >=0{
for k := i; k < length; k++{
if k == length -1{
data[k] = 0
}else {
data[k] = data[k+1]
}
}
length--
return value
}
return -1
}
/**
* 清空
*/
func ClearList(){
data = [MAXSIZE]ElementType{} //数组存储数据元素,最大值为MAXSIZE
length = 0 //线性表当前长度
}
//返回线性表的元素个数
func ListLength() int {
return length
}
func main(){
InitList() //init
var e ElementType = 101
_,_ = ListInsert(e)
var e2 ElementType = 201
_,_ = ListInsert(e2)
var e3 ElementType = 301
_,_ = ListInsert(e3)
var e4 ElementType = 401
_,_ = ListInsert(e4)
var e5 ElementType = 501
_,_ = ListInsert(e5)
fmt.Printf("%v\n",data)
_,e = GetElem(2)
fmt.Println("result:",e)
fmt.Println("len:",ListLength())
fmt.Printf("\n--------------------------------------------------------------------\n")
fmt.Printf("%v\n",data)
_,err := ListInsertByPosition(6,202)
fmt.Println("ERROR:",err)
fmt.Printf("%v\n",data)
fmt.Println("len:",ListLength())
_,e = GetElem(2)
fmt.Println("result:",e)
//./lineMain.go:102:12:
fmt.Printf("\n--------------------------------------------------------------------\n")
ListDeleteForIndex(7)
fmt.Printf("%v\n",data)
fmt.Println("len:",ListLength())
}
go run lineMain.go
[101 201 301 401 501 0]
result: 201
len: 5
[101 201 301 401 501 0]
ERROR:
[101 201 301 401 501 202]
len: 6
result: 201
[101 201 301 401 501 202]
len: 6