Go中append和链表的关系

1.机缘

在与学长的交流中,了解到在Go中链表的增删还有利用append的增删,因为之前有对切片进行删改操作,所以觉得在Go中,可能不需要链表,就可以完成操作所以进行了两者的时间复杂度的比较。

1.append的介绍

在go语言中,append()函数用于为切片动态添加元素,可以将元素添加到切片末尾并返回结果;调用append函数必须用原来的切片变量接收返回值,追加一个元素可使用“slice = append(slice,elem1,elem2)”语句,追加一个切片可使用“slice = append(slice,anotherSlice...)”语句。

  • append()用来将元素添加到切片末尾并返回结果。
  • 调用append函数必须用原来的切片变量接收返回值
  • append追加元素,如果slice还有容量的话,就会将新的元素放在原来slice后面的剩余空间里,当底层数组装不下的时候,Go就会创建新的底层数组来保存这个切片,slice地址也随之改变。
  • 分配了新的地址后,再把原来slice中的元素逐个拷贝到新的slice中,并返回。

append不仅可以添加元素,也可以添加切片。

2.计算两者运行时间大小的时间函数

now := time.Now()//计算出当前的时间
Time = time.Now().UnixMilli() - now.UnixMilli()//用当前的时间减去之间记录的时间

我们可以利用time函数进行计时,这里我们用的纳秒,还可以用毫秒,多种时间计算方法。

2.操作

1.链表的操作

我们编写了链表的增删,因为切片只能进行扩展,不能在特定位置进行删除,我们主要用链表的删除操作来计时,看看两者的特定位置插入的和直接插入的两者时间。

package operator

import (
	"fmt"
	"time"
)

type node struct {
	id   int
	next *node
}

type list struct {
	head *node
}

func NewList() *list {
	l := &list{}
	l.head = &node{}
	l.head.next = nil
	return l
}

func (l *list) Insert(k int, id int) {
	//if l.head.next == nil {
	//	p := new(node)
	//	p.id = id
	//	p.next = nil
	//	l.head.next = p
	//	//fmt.Println(l.head.next.id)
	//	return
	//}
	i := 0
	t := l.head
	temp := l.head.next
	for i = 1; i < k && temp != nil; i++ {
		//fmt.Println("adsd")
		temp = temp.next
		t = t.next
	}
	//fmt.Println(i, k)
	if i == k {
		p := new(node)
		p.id = id
		p.next = nil
		t.next = p
		p.next = temp
		//fmt.Println(p.id)
		//temp.next = p
	} else {
		fmt.Println("没有找到")
		return
	}
	return
}

func (l *list) delete(k int) {
	t := l.head
	temp := l.head.next
	i := 0
	for i = 1; i < k; i++ {
		if temp.next == nil {
			break
		}
		temp = temp.next
		t = t.next
	}
	if i == k {
		if temp.next == nil {
			t.next = nil
		} else {
			t.next = temp.next
		}
	} else {
		fmt.Println("没有找到")
		return
	}
	return
}
func (l *list) printf() {
	fmt.Println("打印数据为")
	for temp := l.head.next; temp != nil; temp = temp.next {
		fmt.Print(temp.id, " ")
	}
}
func Analyse01() {
	l := NewList()

	l.Insert(1, 8)
	l.Insert(2, 5)
	l.Insert(3, 0)
	for i := 0; i < 90000; i++ {
		l.Insert(2, i)
	}
	//l.Insert(5, 1)
	//l.Insert(2, 2)
	//l.Insert(2, 9)
	//l.printf()
	//l.delete(6)
	//l.delete(5)
	//l.printf()
	now := time.Now()
	for i := 0; i < 90000; i++ {
		l.delete(2)
	}
	fmt.Println(time.Now().UnixMilli() - now.UnixMilli())
}

2.append对切片进行删除

这里是我们进行对切片特定地方删除的操作,我们也可以使用这个进行扩展操作,统计时间。

package operator

import (
	"fmt"
	"time"
)

func Analyse02() {

	var a []int
	a = append(a, 1)
	a = append(a, 2)
	for i := 0; i < 90000; i++ {
		a = append(a, i)
	}
	s := time.Now()
	for i := 0; i < 90000; i++ {
		a = append(a[0:1], a[2:]...)
	}
	fmt.Println(time.Now().UnixMilli() - s.UnixMilli())
}

3.特定位置删除的时间

  从图中我们可以看出,相同的数据下,两者的时间差距是很大的

4.直接进行插入

 我们数据增加到90000000时再进行增加,就会发现链表的时间远远大于append

 但是当我们把数据减少到90000时就会发现两者的差距很小了,

3.总结

我们可以看出来两者的比较,所以就明白了,append进行删除的时候,其实是对这个切片重新进行了空间分配,所以这样大大增加了时间,但是再扩展的时候只是进行增加,扩容的时候并且还是以二倍的速度进行扩容,所以这个时间就是大大减少了,所以我们在合理的时候需要用到合理的方法,这样才可以是我们编写的程序的时间大大减少。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值