golang实现顺序存储结构的线性表的增、删、查、改操作

--------------------------------------------
 线性表的定义
--------------------------------------------
通俗理解:
  一个班级的小朋友,一个跟着一个排着队,有一个打头,有一个收尾,当中的的小朋友每一个都知道
他前面的一个是谁,他后面的一个是谁,这样如同一根线把他们串联起来了。就可以称之为线性表。

专业术语:
   线性表(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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值