一、Go基础知识13、list详解

一、list和slice的区别

在Go语言中,listslice是两种不同的数据结构,它们有着不同的特性和用法。

1、Slice(切片)

切片是Go语言中一种动态数组的抽象。它由三个部分组成:指针、长度和容量。切片提供了一种方便而灵活的方式来操作序列,可以动态地增加或减少其大小。

示例

package main

import "fmt"

func main() {
    // 创建一个切片
    numbers := []int{1, 2, 3, 4, 5}

    // 打印切片的内容
    fmt.Println("Original slice:", numbers)

    // 修改切片中的元素
    numbers[0] = 10
    fmt.Println("Modified slice:", numbers)

    // 切片的追加
    numbers = append(numbers, 6, 7, 8)
    fmt.Println("Slice after append:", numbers)

    // 切片的切割
    slice := numbers[1:4]
    fmt.Println("Sliced slice:", slice)
}

结果:

Original slice: [1 2 3 4 5]
Modified slice: [10 2 3 4 5]
Slice after append: [10 2 3 4 5 6 7 8]
Sliced slice: [2 3 4]

解释
在这个例子中,我们创建了一个切片numbers,并对其进行了修改、追加和切割操作。

2、List(链表)

Go语言的标准库中没有直接提供链表(list)的实现,但可以使用container/list包来实现双向链表。链表是一种线性表的数据结构,其中的元素是通过指针相互连接的。

示例

package main

import (
	"container/list"
	"fmt"
)

func main() {
	// 创建一个链表
	myList := list.New()

	// 在链表末尾添加元素
	myList.PushBack(1)
	myList.PushBack(2)
	myList.PushBack(3)

	// 遍历链表并打印元素
	fmt.Print("List elements: ")
	for e := myList.Front(); e != nil; e = e.Next() {
		fmt.Print(e.Value, " ")
	}
	fmt.Println()
}

结果:

List elements: 1 2 3

解释
在这个例子中,我们使用container/list包创建了一个链表myList,然后在链表的末尾添加了三个元素,并通过遍历打印了链表中的元素。

3、区别总结

  1. 底层结构:

    • 切片是基于数组的动态数组抽象,具有指针、长度和容量。
    • 链表是由节点通过指针相互连接的数据结构。
  2. 操作灵活性:

    • 切片提供了方便的动态操作,支持追加、切割等操作。
    • 链表支持在任意位置插入和删除元素,但对于访问元素,需要从头或尾开始遍历。
  3. 性能特征:

    • 切片在尾部追加元素的性能较好,时间复杂度为 O(1)。
    • 链表在任意位置插入和删除元素的性能较好,时间复杂度为 O(1)。

选择使用切片还是链表取决于具体的应用场景和操作需求。在大多数情况下,切片是更常见和更高效的选择,但在需要频繁插入和删除操作的情况下,链表可能更合适。

二、list的用法

在Go语言中,list是通过container/list包实现的双向链表。list提供了在链表的前后插入和删除元素的方法,是一种非常灵活的数据结构。

举例展示list包提供的一些基本操作,包括在链表的前后插入、删除元素,以及正向和反向遍历链表。

示例

package main

import (
	"container/list"
	"fmt"
)

func main() {
	// 创建一个新的链表
	myList := list.New()

	// 在链表的末尾添加元素
	myList.PushBack(1)
	myList.PushBack(2)
	myList.PushBack(3)

	// 在链表的开头添加元素
	myList.PushFront(0)

	// 遍历链表并打印元素
	fmt.Print("List elements (forward): ")
	for e := myList.Front(); e != nil; e = e.Next() {
		fmt.Print(e.Value, " ")
	}
	fmt.Println()

	// 遍历链表并打印元素(反向)
	fmt.Print("List elements (backward): ")
	for e := myList.Back(); e != nil; e = e.Prev() {
		fmt.Print(e.Value, " ")
	}
	fmt.Println()

	// 在特定元素之后插入新元素
	insertAfterElement := myList.Front().Next()
	myList.InsertAfter(10, insertAfterElement)

	// 删除特定元素
	deleteElement := myList.Front().Next().Next().Next()
	myList.Remove(deleteElement)

	// 再次遍历链表并打印元素
	fmt.Print("List elements after modifications: ")
	for e := myList.Front(); e != nil; e = e.Next() {
		fmt.Print(e.Value, " ")
	}
	fmt.Println()
}

结果:

List elements (forward): 0 1 2 3 
List elements (backward): 3 2 1 0 
List elements after modifications: 0 1 2 10 3 

解释
在这个例子中,我们首先创建了一个新的链表myList,然后在链表的末尾和开头分别添加了一些元素。接着,我们通过两种方式遍历链表(正向和反向)并打印元素。

随后,我们在特定元素之后插入了一个新元素(在元素值为2的位置插入了值为10的元素),然后删除了另一个特定的元素(元素值为3的元素)。最后,再次遍历链表并打印修改后的元素。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风不归Alkaid

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值