通过copy函数可以把一个切片内容复制到另一个切片中
(1)把长切片拷贝到短切片中
package main
import "fmt"
func main() {
s1 := []int {1,2}
s2 := []int{3,4,5,6}
//copy的是角标,不会增加元切片的长度
copy(s1,s2)
fmt.Println(s1) //[3 4]
fmt.Println(s2) //[3 4 5 6]
}
(2)把短切片拷贝到长切片中
package main
import "fmt"
func main() {
s1 := []int {1,2}
s2 := []int{3,4,5,6}
//copy的是角标,不会增加元切片的长度
copy(s2,s1)
fmt.Println(s1) //[1 2]
fmt.Println(s2) //[1 2 5 6]
}
(3)把切片片段拷贝到切片中
package main
import "fmt"
func main() {
s1 := []int {1,2}
s2 := []int{3,4,5,6}
//copy的是角标,不会增加元切片的长度
copy(s1,s2[1:3])
fmt.Println(s1) //[[4 5]
fmt.Println(s2) //[3 4 5 6]
}
package main
import (
"fmt"
"sort"
)
func main() {
num := []int{1,7,3,5,2}
//升序排序
sort.Ints(num)
fmt.Println(num) //[1 2 3 5 7]
//降序排序
sort.Sort(sort.Reverse(sort.IntSlice(num)))
fmt.Println(num) //[7 5 3 2 1]
}
(1)双向链表的结构
双向链表结构中元素在内存中不是紧邻空间,而是每个元素中存放上一个元素和后一个元素的地址
双向链表的优点
双向链表的缺点
(2)双向链表容器List
在Go语言标准库的container/list包提供了双向链表List
List结构体定义如下
// List represents a doubly linked list.
// The zero value for List is an empty list ready to use.
type List struct {
root Element // sentinel list element, only &root, root.prev, and root.next are used
len int // current list length excluding (this) sentinel element
}
其中Element结构体定义如下
// Element is an element of a linked list.
type Element struct {
// Next and previous pointers in the doubly-linked list of elements.
// To simplify the implementation, internally a list l is implemented
// as a ring, such that &l.root is both the next element of the last
// list element (l.Back()) and the previous element of the first list
// element (l.Front()).
next, prev *Element
// The list to which this element belongs.
list *List
// The value stored with this element.
Value interface{}
}
(1)直接使用container/list包下的New()新建一个空的List
添加,遍历,取首尾,取中间元素
package main
import (
"container/list"
"fmt"
)
func main() {
//实例化
mylist := list.New()
fmt.Println(mylist)
//添加
mylist.PushFront("a") //["a"]
mylist.PushBack("b") //["a","b"]
mylist.PushBack("c") //["a","b","c"]
//在最后一个元素的前面添加
mylist.InsertBefore("d",mylist.Back()) //["a","b","d","c"]
mylist.InsertAfter("e",mylist.Front()) //["a","e","b","d","c"]
//遍历
for e := mylist.Front(); e != nil; e = e.Next(){
fmt.Print(e.Value, " ") //a e b d c
}
fmt.Println("")
//取首尾
fmt.Println(mylist.Front().Value) //a
fmt.Println(mylist.Back().Value) //c
//取中间的元素,通过不断的Next()
n := 3
var curr *list.Element
if n > 0 && n <= mylist.Len(){
if n == 1 {
curr = mylist.Front()
}else if n == mylist.Len(){
curr = mylist.Back()
}else {
curr = mylist.Front()
for i := 1; i < n; i++{
curr = curr.Next()
}
}
}else {
fmt.Println("n的数值不对")
}
fmt.Println(curr.Value) //b
}
(2)移动元素
package main
import (
"container/list"
"fmt"
)
func main() {
//实例化
mylist := list.New()
fmt.Println(mylist)
//添加
mylist.PushFront("a") //["a"]
mylist.PushBack("b") //["a","b"]
mylist.PushBack("c") //["a","b","c"]
//在最后一个元素的前面添加
mylist.InsertBefore("d",mylist.Back()) //["a","b","d","c"]
mylist.InsertAfter("e",mylist.Front()) //["a","e","b","d","c"]
//移动,把第一个元素一道最后一个元素的前面
mylist.MoveBefore(mylist.Front(),mylist.Back())
//mylist.MoveAfter(mylist.Back(),mylist.Front())
//把最后一个元素移动到最前面
//mylist.MoveToFront(mylist.Back())
//把第一个元素移动到最后面
//mylist.MoveToBack(mylist.Front())
for e := mylist.Front(); e != nil; e = e.Next(){
fmt.Print(e.Value, " ") //e b d a c
}
}
(3)删除
mylist.Remove(mylist.Front())
(1)循环链表特点是没有节点的指针域为nil,通过任何一个元素都可以找到其它元素
环形链表结构如下
双向循环链表和双向链表区别
(2)在container/ring包下结构体Ring源码如下
// A Ring is an element of a circular list, or ring.
// Rings do not have a beginning or end; a pointer to any ring element
// serves as reference to the entire ring. Empty rings are represented
// as nil Ring pointers. The zero value for a Ring is a one-element
// ring with a nil Value.
//
type Ring struct {
next, prev *Ring
Value interface{} // for use by client; untouched by this library
}
(3)创建和查看
package main
import (
"container/ring"
"fmt"
)
func main() {
//r代表整个循环链表,又代表第一个元素
r := ring.New(5)
r.Value = 0
r.Next().Value = 1
r.Next().Next().Value = 2
//r.Next().Next().Next().Value = 3
//r.Next().Next().Next().Next().Value = 4
r.Prev().Value = 4
r.Prev().Prev().Value = 3
//查看元素内容
//循环链表有几个元素,func就执行几次,i当前执行元素的内容
r.Do(func(i interface{}) {
fmt.Print(i, " ") //0 1 2 3 4
})
fmt.Println("")
//取中间元素,用移动
fmt.Println(r.Move(3).Value) //3
}
(4)增加
package main
import (
"container/ring"
"fmt"
)
func main() {
//r代表整个循环链表,又代表第一个元素
r := ring.New(5)
r.Value = 0
r.Next().Value = 1
r.Next().Next().Value = 2
//r.Next().Next().Next().Value = 3
//r.Next().Next().Next().Next().Value = 4
r.Prev().Value = 4
r.Prev().Prev().Value = 3
//增加
r1 := ring.New(2)
r1.Value = 5
r1.Next().Value = 6
r.Link(r1)
r.Do(func(i interface{}) {
fmt.Print(i, " ") //0 5 6 1 2 3 4
})
}
(5)删除
package main
import (
"container/ring"
"fmt"
)
func main() {
//r代表整个循环链表,又代表第一个元素
r := ring.New(5)
r.Value = 0
r.Next().Value = 1
r.Next().Next().Value = 2
//r.Next().Next().Next().Value = 3
//r.Next().Next().Next().Next().Value = 4
r.Prev().Value = 4
r.Prev().Prev().Value = 3
//删除
r.Unlink(1)
r.Do(func(i interface{}) {
fmt.Print(i, " ") //0 2 3 4
})
}
删除后面两个
//删除
r.Unlink(2)
r.Do(func(i interface{}) {
fmt.Print(i, " ") //0 3 4
})
r.Next()删除
//删除
r.Next().Unlink(2)
r.Do(func(i interface{}) {
fmt.Print(i, " ") //0 1 4
})qu
超出范围,取5的余数
//删除
r.Unlink(6)
r.Do(func(i interface{}) {
fmt.Print(i, " ") //0 2 3 4
})