线性表-单向链表

线性表

动态数组(切片)、链表、栈、队列都属于线性结构。

线性表是零个或者多个数据元素的有限序列,数据元素之间是有顺序的数据元素个数是有限的数据元素的类型是相同的。

头节点只有一个后继节点,尾节点只有一个前继节点,中间节点既有前继节点又有后续节点。

线性表的抽象数据类型定义
ADT线性表(List)
Data
线性表的数据对象集合为{ a1, a2, ……, an },每个元素的类型均为DataType。其中,除第一个元素a1外,每个元素有且只有一个直接前驱元素,除了最后一个元素an外,每个元素有且只有一个直接后继元素。数据元素之间的关系是一一对应的。

Operation(操作)
// 初始化,建立一个空的线性表L。
InitList(*L);
// 若线性表为空,返回true,否则返回false
ListEmpty(L);
// 将线性表清空
ClearList(*L);
// 将线性表L中的第i个位置的元素返回给e
GetElem(L, i, *e);
// 在线性表L中的第i个位置插入新元素e
ListInsert(*L, i, e);
// 删除线性表L中的第i个位置元素,并用e返回其值
ListDelete(*L, i, *e);
// 返回线性表L的元素个数
ListLength(L);
// 销毁线性表
DestroyList(*L);

链表

概念

数据结构中叫结点

数据域
指针域
结点分类

头结点:数据域为空,地址域指向第一个数据结点。没有前驱,只有后继。完整链表有头结点,实际视情况可以没有

数据结点:既有前驱又有后继。

尾结点:也是数据结点。指针域为空。只有前驱,没有后继。

链表的构成
type LinkNode struct {
	Data interface{}
	Next *LinkNode
}
链表的操作方法
1.创建链表
2.打印链表
3.获取链表长度(数据结点的个数,不包含头结点)
4.插入结点:头插法、尾插法,按位置插入
5.按位置插入
6.按数据删除
7.按数据查找
8.销毁链表
go实现链表

创建链表

func (node *LinkNode) Create(Data ...interface{}) {
	if node == nil || Data == nil {
		return
	}
	if len(Data) == 0 {
		return
	}
	
	// 循环遍历Data依次取出创建单向链表
	for _, v := range Data {
		//创建新结点,并且初始化
		newNode := new(LinkNode)
		newNode.Data = v
		newNode.Next = nil
		//新结点加入链表
		node.Next = newNode
		//更新新结点为当前结点
		node = node.Next
	}
}

主函数

func main() {
	node := new(LinkNode)
	node.Create(1,2,3,4,5)	
}

打印链表

//递归打印
func (node *LinkNode) Print1() {
	if node == nil {
		return
	}
	if node.Data != nil {
		fmt.Print(node.Data, " ")
	}
	node.next.Print1()
}

//循环打印
func (node *LinkNode) Print2() {
	if node == nil {
		return
	}
	
	for node.Next != nil {
		node = node.Next	//跳过头结点
		fmt.Print(node.Data, " ")  //打印		
	}
}

获取链表的长度

func (node *LinkNode) Length() int {
	if node == nil {
		return -1
	}	
	for node.Next != nil {
		node = node.Next
		i++
	}
	return i
}

头插法

func (node *LinkNode) InsertByHead(Data interface{})  {
	if node == nil {
		return
	}	
	
	//创建新结点,初始化
	newNode := new(LinkNode)
	newNode.Data = Data
	newNode.next = node.next  //新结点指向第一个数据结点 
	
	//头结点下一个节点赋值为新结点
	node.Next = newNode
}

尾插法

func (node *LinkNode) InsertByTail(Data interface{})  {
	if node == nil {
		return
	}	
	//遍历
	for node.next != nil {
		node = node.next
	}
	
	//创建新结点,初始化
	newNode := new(LinkNode)
	newNode.Data = Data
	newNode.next = nil
	
	node.next = newNode
}

按照位置插入结点

func (node *LinkNode) InsertByIndex(Data interface{}, index int)  {
	//容错处理
	if node == nil {
		return
	}	
	if index < 0 || index > node.Length() {
		return
	}

	//定义前一个节点
	preNode := node
	//找寻插入位置
	for i:= 0; i < index; i++ {
		//prenode指向当前结点,然后node变更为下一个结点
		preNode = node
		node = node.Next
	}	
		
	//创建新结点
	newNode := new(LinkNode)
	newNode.Data = Data
	newNode.next = nil
	
	preNode.next = newNode
	newNode.next = node
}
比较顺序表和链式表

顺序表:内存连续,查找快,内存占用小

缺点:增,删效率低

场景:数据批量查询

链式表:散乱存储,增删效率高,

缺点:查询效率低,需要额外占用内存

场景:增删频繁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值