(4)Go实现单链表

链表(Linked list)是一种 “动态数据结构”,链表由节点构成node链接构成,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针。
相比数组,数组的内存地址是连续的,而链表不用连续的内存地址
链表是动态数据结构,用链表组成的栈和队列数据结构,不用做扩容和缩容操作

node 节点一般存储两个元素,本节点内容content和下一个节点指针next,结构如下
type Node struct{
      Content  interface{}
      Next     *Node
}

链表由节点组成,由3个元素组成,length链表长度,head头节点,tail尾节点,结构如下
type LinkedList struct{
        Length    int
        Head    *Node
        Tail    *Node    
}
// 单链表数据结构的实现
// 节点
type node struct {
	Item interface{}
	Next *node
}

// 链表
type linkedList struct {
	Length    int
	DummyHead *node //虚拟头节点,可以统一头节点和其他节点的操作,达到简化逻辑的效果
}

func NewNode() *node {
	return &node{
		Item: nil,
		Next: nil,
	}
}

func NewLinkedList() *linkedList {
	return &linkedList{
		Length:    0,
		DummyHead: &node{},  
	}
}

func (l *linkedList) Add(index int, n *node) {
	if index < 0 || index > l.Length {
		log.Fatal("failed to add, index 超出范围.")
	}
	prev := l.DummyHead
	for i := 0; i < index; i++ {
		prev = prev.Next
	}

	n.Next = prev.Next
	prev.Next = n
	l.Length++
}

func (l *linkedList) AddFirst(n *node) {
	l.Add(0, n)
}

func (l *linkedList) AddLast(n *node) {
	l.Add(l.Length-1, n)
}

// 输入index,返回index位节点
func (l *linkedList) Get(index int) (cur *node, err error) {
	if index < 0 || index > l.Length {
		err = errors.New("failed to traverse, index out of range.")
		return nil, err
	}

	if l.Length == 0 {
		log.Fatal("failed to traverse,linkedList is empty.")
	}

	cur = l.DummyHead //虚拟头节点

	for i := 0; i <= index; i++ {
		cur = cur.Next //index位节点
	}
	return cur, nil
}

// 修改index节点
func (l *linkedList) Modify(index int, n *node) {
	if index < 0 || index > l.Length {
		log.Fatal("failed to modify, index out of range.")
	}

	if l.Length == 0 {
		log.Fatal("failed to traverse,linkedList is empty.")
	}

	cur, _ := l.Get(index)

	cur.Item = n.Item
	cur.Next = n.Next
}

// 修改index节点内容
func (l *linkedList) ModifyContent(index int, item interface{}) {
	if index < 0 || index > l.Length {
		log.Fatal("failed to modifyContent, index out of range.")
	}

	if l.Length == 0 {
		log.Fatal("failed to traverse,linkedList is empty.")
	}

	cur, _ := l.Get(index)
	cur.Item = item

}

func (l *linkedList) Delete(index int) error {
	if index < 0 || index > l.Length {
		return errors.New("failed to delete, index out of range.")
	}

	prev := l.DummyHead
	for i := 0; i < index; i++ {
		prev = prev.Next
	}

	delNode := prev.Next
	prev.Next = delNode.Next
	delNode = nil
	l.Length--
	return nil
}

// 查找链表中是否有元素e
func (l *linkedList) Contains(n *node) bool {
	if l.Length == 0 {
		return false
	}

	cur := l.DummyHead //虚拟头节点

	for i := 0; i <= l.Length-1; i++ {
		cur = cur.Next //index位节点
		if cur == n {
			return true
		}
	}
	return false
}

// 获取链表中所有内容
func (l *linkedList) Traverse() []interface{} {
	resp := []interface{}{}
	buf := l.DummyHead.Next
	for buf != nil {
		resp = append(resp, buf.Item, "->")
		buf = buf.Next
	}
	resp = append(resp, nil)
	return resp
}
// 测试链表
func main() {
	l := linked_list1.NewLinkedList()
	q := linked_list1.NewNode()

	for i := 0; i < 5; i++ {
		buf := linked_list1.NewNode()
		buf.Item = i
		l.AddFirst(buf)
		resp := l.Traverse()
		fmt.Println(resp)
	}
	fmt.Println(l.Contains(q))

	for i := 0; i < 5; i++ {
		l.ModifyContent(i, 8+i)
		resp := l.Traverse()
		fmt.Println(resp)
	}

	for i := 0; i < 5; i++ {
		l.Delete(4 - i)
		resp := l.Traverse()
		fmt.Println(resp)
	}

	l.Modify(1, q)
	resp := l.Traverse()
	fmt.Println(resp)
}
// 测试结果
[0 -> <nil>]
[1 -> 0 -> <nil>]
[2 -> 1 -> 0 -> <nil>]
[3 -> 2 -> 1 -> 0 -> <nil>]
[4 -> 3 -> 2 -> 1 -> 0 -> <nil>]
false
[8 -> 3 -> 2 -> 1 -> 0 -> <nil>]
[8 -> 9 -> 2 -> 1 -> 0 -> <nil>]
[8 -> 9 -> 10 -> 1 -> 0 -> <nil>]
[8 -> 9 -> 10 -> 11 -> 0 -> <nil>]
[8 -> 9 -> 10 -> 11 -> 12 -> <nil>]
[8 -> 9 -> 10 -> 11 -> <nil>]
[8 -> 9 -> 10 -> <nil>]
[8 -> 9 -> <nil>]
[8 -> <nil>]
[<nil>]
2019/04/16 23:59:31 failed to modify, index out of range.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值