Go语言学习笔记【10】 数据结构之单链表、双链表、循环链表

【声明】

非完全原创,部分内容来自于学习其他人的理论和B站视频。如果有侵权,请联系我,可以立即删除掉。

一、概念

1、线性表

线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(循环链表的首位相连,因此不符合该定义,但它也是线性表的一种)。
线性表是一种逻辑上的结构, 主要强调数据之间的关系,不关心底层如何实现。因此线性表可以用指针的方式,也可以用数组的方式来实现

  • 数组、链表、栈、队列是四种最常见的线性表

1.1、顺序表

顺序表是在计算机内存中以数组的形式保存的线性表,即, 采用顺序存储结构的线性表通常称为顺序表。
线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。

//定义一个长度为1024的顺序表
const maxLen = 1024
type sequence_list struct {
   
	data [maxLen]int
	size int
}

1.2、单链表

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素 + 指针。元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

优缺点

  • 优点:单向链表增加删除节点简单。遍历时候不会死循环
  • 缺点:只能从头到尾遍历。只能找到后继,无法找到前驱

1.3、双链表

与单链表不一样的是,双链表中每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

优缺点:

  • 优点:可以找到前驱和后继,因此遍历链表时可从后往前,也可以从前往后
  • 缺点:比单链表多一个指针存储空间。

二、单链表的实现

本文中用链式结构是实现了单链表,数组的实现方式参考:https://www.cnblogs.com/pureayu/p/13614443.html

1、特点

由各个内存结构通过一个指向下一个结点的指针链接在一起组成,每一个内存结构都存在后继内存结构(链尾除外),内存结构由数据域和指针域组成。
在这里插入图片描述

2、说明

(1)为了方便,单链表带有一个不存放任何数据的头节点。主要是为了在操作链表时,不用单独区分链表头指针是否为空,方便代码的书写
(2)主要的方法有:

方法 说明
IsEmpty() bool 判断单链表是否为空
Size() 获取链表的长度
CreateList() *BookName 创建一个单链表
GetValueInfo() string 获取当前结点数据域的字符串
AddFirst(newNode *BookName) 链表头部插入元素
AddLast(newNode *BookName) 链表尾部插入元素
RemoveFirst() *BookName 删除链表头部元素,并返回已删除的元素
RemoveLast() *BookName 删除链表尾部元素,并返回已删除的元素
GetFirst() *BookName 获取链表头部元素
GetLast() *BookName 获取链表尾部元素
Contains(node *BookName) bool 判断链表中是否存在某结点
List() 打印单链表中的所有元素及指向关系
Reverse() 将链表进行反转

3、代码

package sll

import "fmt"

type BookName struct {
   
	Rank int
	Name string
	Next *BookName
}

//单链表的头结点值设为空, 指针设为nil
func CreateList() *BookName {
   
	return &BookName{
   }
}

func (head *BookName) GetValueInfo() string {
   
	return strconv.Itoa(head.Rank) + " " + head.Name
}

func (head *BookName) IsEmpty() bool {
   
	return head.Next == nil
}

func (head *BookName) Size() int {
   
	cnt := 0
	for tmp := head; tmp.Next != nil; tmp = tmp.Next {
   
		cnt++
	}
	return cnt
}

//尾部插入元素
func (head *BookName) AddLast(newNode *BookName) {
   
	var tmp *BookName
	for tmp = head; tmp.Next != nil; tmp = tmp.Next {
   
	}
	tmp.Next = newNode
}

//头部插入元素
func (head *BookName) AddFirst(newNode *BookName) {
   
	var tmp *BookName = newNode
	tmp.Next = 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值