golang面试题单向链表和双向链表
2023-03-20 15:58 dribs 阅读(64) 评论(0) 收藏 举报甲流难受中,简单发一个链表
1.单项列表
package main
import (
"fmt"
"strconv"
)
type Node struct {
value int
next *Node
}
type Linklist struct {
len int
head *Node
tail *Node
}
//构造函数linklist
func NewLinklist() *Linklist {
return &Linklist{}
}
func (l *Linklist) Append(value int) *Linklist {
//1.构建实例创建元素,next悬空为nil
node := &Node{value: value}
//node.next = nil //默认是nil
//2.老尾巴指向node
//2.1 如果tail为空 即一个元素也没有,tail此时为nil,nil是无法next的,head和tail都是该node.len==0,l.head=nil
if l.tail == nil {
l.head = node
} else {
//如果至少有一个元素,尾巴就可以指到下一个节点
l.tail.next = node
}
//3.更新尾巴
l.tail = node
l.len++
return l
}
//遍历链表取出各个元素
func (l *Linklist) Iternodes() {
//链表头节点
p := l.head
for p != nil {
fmt.Println(p)
p = p.next
}
}
func (n *Node) String() string {
var s string
if n.next == nil {
s = "null"
} else {
s = strconv.Itoa(n.next.value)
}
return fmt.Sprintf("%d --> %s", n.value, s)
}
func main() {
linklist := NewLinklist()
//fmt.Println(linklist)
l := linklist.Append(1111).Append(22)
fmt.Println(l)
l.Iternodes()
}
2.双向链表
package main
import (
"errors"
"fmt"
"strconv"
)
type Node struct {
item int
next *Node //nil
prev *Node //nil
}
type DoubleLinkList struct {
len int
head *Node
tail *Node
}
func NewDoubleLinkList() *DoubleLinkList {
return &DoubleLinkList{}
}
func (n *Node) String() string {
var s1, s2 string
if n.next == nil {
s1 = "null"
} else {
s1 = strconv.Itoa(n.next.item)
}
if n.prev == nil {
s2 = "null"
} else {
s2 = strconv.Itoa(n.prev.item)
}
return fmt.Sprintf("%s<--%d--->%s", s2, n.item, s1)
}
//遍历链表取出各个元素
func (l *DoubleLinkList) Iternodes() []*Node {
//向后遍历 找链表头节点
p := l.head
//复用这个for循环给insert的方法用
nodelist := make([]*Node, 0, l.len)
for p != nil {
nodelist = append(nodelist, p)
//insert方法的时候暂时注释掉该打印便于查看
//fmt.Println(p)
p = p.next
}
return nodelist
//向后遍历 找链表尾节点
//p = l.tail
//for p != nil {
// fmt.Println(p)
// p = p.prev
//}
}
//追加元素
func (l *DoubleLinkList) Append(value int) *DoubleLinkList {
//1、构造node
node := new(Node)
node.item = value
//node.next=nil 初始化默认为nil
//node.prev=nil 初始化默认为nil
//2、老尾巴指向node
if l.tail == nil {
//2.1一个元素也没有,头尾都是当前node
l.head = node
//l.tail = node //至少有一个的时候也会挪尾巴,抽出来
//node.prev = nil //l.tail,prev ==nil //默认为nil 一个没有追加了一个,此时prev next都还是nil
//node.next = nil //l.tail.next ==nil //默认不写为nil
} else {
//至少有一个的时候,head头不动,前一个的next指下一个,下一个的prev指前一个尾巴、其他不动
//l.head //尾部追加的时候头不动
//l.tail.prev //不动
l.tail.next = node
node.prev = l.tail
//node.next = nil //默认为空
//l.tail = node //在没元素的时候追加一个也会挪尾巴,抽出来
}
//更新尾巴
l.tail = node
l.len++
return l
}
func (l *DoubleLinkList) Pop() error {
//1、没有任何元素的时候弹出错误,没有元素 即l.len==0 或 l.tail == nil 或 l.head==nil
if l.len == 0 {
return errors.New("empty")
} else if l.head == l.tail {
//只有一个元素,l.head==0xc000004090 l.tail==0xc000004090,所以上面在没有元素的时候 不推荐l.head==l.tail判断
//上面已经把0个元素过滤掉了,所以这里l.head==l.tail做判断不会出现0个元素的情况
//移除节点后 没有了节点 所以head和tail都是nil
l.head = nil
l.tail = nil
} else {
//不止一个元素的时候弹出
//1、断开手拉手,即前一个(l.tail.prev)的next = nil
//2、更新尾巴 即 l.tail = 前一个节点
//其他不必要的手拉手 不管 即 l.tail.prev =nil l.tail.next=nil
//前面的节点不动,更新len
l.tail.prev.next = nil
l.tail = l.tail.prev
}
l.len--
return nil
}
func (l *DoubleLinkList) Insert(index, value int) error {
//如果索引为负数
if index < 0 {
return errors.New("invalid position")
}
//index>0
//定义当前节点
var current *Node
//Iternodes至少有一个元素的时候
for i, node := range l.Iternodes() {
//找到当前节点
if index == i {
current = node
break
}
//Iternodes至少有一个元素的时候,如果遍历完Iternodes还没有和insret的索引匹配证明索引超界,那也追加
//如果Iternodes 没有元素的时候 也会执行尾部追加 append会写两次,所以此处注释掉挪外面
//else {
// l.Append(value)
//}
}
//如果没找到,可能超界;也可能这个时候for循环也没走即Iternodes里没有任何元素,就尾部追加
if current == nil {
l.Append(value)
return nil
}
//找到了插入点,一定不是尾部追加
//分两种 1是开头插入 2是中间插入 都不会动他的尾巴
node := new(Node)
node.item = value
//开头插入的条件 index=0 或current.prev = nil 或 l.head = nil
if index == 0 {
//当前节点的prev指到新增的节点
current.prev = node
//头 改成新增节点
l.head = node
//新头的下一个指到当前节点
l.head.next = current //node.next = current
} else {
node.prev = current.prev
node.prev.next = node
current.prev = node
current.prev.next = current //node.next = current
}
l.len++
fmt.Println(current)
return nil
}
func main() {
dll := NewDoubleLinkList()
l := dll.Append(100).Append(200).Append(300)
fmt.Println(l)
l.Iternodes()
fmt.Println("=====Pop======")
p := l.Pop()
fmt.Println(p)
l.Iternodes()
fmt.Println("------insert------")
l.Insert(1, 50)
fmt.Println(l.Iternodes())
}
浙公网安备 33010602011771号