• Go-单链表-栈和队列


    package main
    
    import (
    	"errors"
    	"fmt"
    	"log"
    )
    
    // 单链表
    // 特征:
    //		1. 每个节点都包含指向下一个节点的指针 next
    //		2. 链表逻辑上是序列,但在内存中存储是不规则的
    // 实现:
    //		1. 头节点(根节点) head 单链表的起始位置,头节点不存放任何数据
    //		2. 链表用来实现队列、栈、有序序列(插入排序)
    //		3. 链表方法:
    //			a. 添加一个节点 Add
    //			b. 移除一个节点
    //			c. 遍历节点
    
    // ValNode 值节点,存放所需数据,至于数据是什么,已经不重要,重要的是有一个指向下一个值节点的指针 next
    type ValNode struct {
    	// data 存放数据
    	data interface{}
    	// 指向下一个节点的值节点指针,如果没有则为空地址 nil
    	next *ValNode
    }
    
    // SingleLink 单链表,包含一个指向链表头部的指针 head
    type SingleLink struct {
    	// 头指针 head 指向链表的头部
    	head *ValNode
    }
    
    func NewSingleLink() *SingleLink {
    	return &SingleLink{
    		head: &ValNode{},
    	}
    }
    
    // AddNode 在尾部添加一个节点: 找打尾部节点,将尾部节点的next指向新增加的节点
    func (sl *SingleLink) AppendNode(v *ValNode)  {
    	// 1. 找到尾部
    	tmp := sl.head
    	for tmp.next != nil {
    		tmp = tmp.next
    	}
    	// 2. 在尾部添加一个节点
    	tmp.next =  v
    }
    
    // 在尾部删除一个节点: 判断链表是否为空,判断链表是否只有一个元素,找到链表最后的上一个元素将next置为nil
    func (sl *SingleLink) PopNode() (v *ValNode, err error) {
    	// 1. 判断是否是空链表, 空链表则返回空链表错误
    	if sl.head.next == nil {
    		err = errors.New("链表为空")
    		return
    	}
    
    	// 2. 判断链表是否只有一个元素,如果为一个元素则将 head头节点的next置为 nil
    	if sl.head.next.next == nil {
    		v = sl.head.next
    		sl.head.next = nil
    	}
    	// 3. 找到链表的上一个元素将next置为nil
    	tmp := sl.head
    	for tmp.next.next != nil {
    		tmp = tmp.next
    	}
    	v = tmp.next
    	tmp.next = nil
    	return
    }
    
    // 在头部删除一个节点: 判断链表是否为空,判断链表是否只有一个元素,将链表头指向链表头指向的下一个元素
    func (sl *SingleLink) PopLeftNode() (v *ValNode, err error) {
    	// 1. 判断是否是空链表, 空链表则返回空链表错误
    	if sl.head.next == nil {
    		err = errors.New("链表为空")
    		return
    	}
    
    	// 2. 判断链表是否只有一个元素,如果为一个元素则将 head头节点的next置为 nil
    	if sl.head.next.next == nil {
    		v = sl.head.next
    		sl.head.next = nil
    	}
    	// 3. 获取链表头指向的下一个元素,并将链表头指向的下一个元素的下一个元素
    	v = sl.head.next
    	sl.head.next = sl.head.next.next
    	return
    }
    
    // ListLink 遍历列表,判断链表是否为空
    func (sl *SingleLink) ListLink() {
    	// 1. 判断是否是空链表
    	if sl.head.next == nil {
    		fmt.Println("SingleLink empty")
    		return
    	}
    	// 2. 遍历链表
    	tmp := sl.head.next
    	for tmp != nil {
    		fmt.Println(tmp.data)
    		tmp = tmp.next
    	}
    }
    
    // 通过链表的 AppendNode 和 PopNode实现了栈
    // 通过链表的 AppendNode 和 PopLeftNode实现了队列
    
    func main() {
    	sl := NewSingleLink()
    	node1 := &ValNode{
    		data: 100,
    	}
    	node2 := &ValNode{
    		data: 200,
    	}
    	sl.AppendNode(node1)
    	sl.AppendNode(node2)
    	node3, err := sl.PopNode()
    	if err != nil {
    		log.Println(err)
    	}
    	fmt.Println(node3)
    	sl.ListLink()
    }
    

      

  • 相关阅读:
    常用品牌交换机镜像抓包配置
    BGP知识点备忘录
    IS-IS路由协议地址详解
    Linux msmtp+mutt发邮件
    Linux添加一临时用户拥有root权限最快方式
    ELK5.0全程普通用户源码安装指南(CentOS6.5)
    改变文件的拥有者和改变文件的拥有组
    Linux chmod命令详解
    Linux目录介绍
    php时间戳转化成时间相差8小时问题
  • 原文地址:https://www.cnblogs.com/2bjiujiu/p/14428653.html
Copyright © 2020-2023  润新知