链表

作者: EricDD | 来源:发表于2023-02-18 17:11 被阅读0次
链表.jpg 链表-存储原理.jpg 链表操作.jpg 链表操作1.jpg 链表操作2.jpg 链表优缺点.jpg

代码示例

package main

import (
    "errors"
    "fmt"
    "strconv"
)

// Node 节点
type Node struct {
    data int   // data 节点存储数据
    next *Node // next node 下一个节点
}

// SingletonNode 单向链表
type SingleLinkedList struct {
    head *Node // head 头节点
    size int   // size 链表数量
}

// New 创建单向链表
func New() *SingleLinkedList {
    return &SingleLinkedList{}
}

// GetHead 获得头节点
func (l *SingleLinkedList) GetHead() (error, int) {
    if l.IsEmpty() {
        return errors.New("empty list"), 0
    }

    return nil, l.head.data
}

// GetNode 获得节点
// index 链表索引
func (l *SingleLinkedList) GetNode(index int) (error, int) {
    err, node := l.Node(index)

    if err != nil {
        return err, 0
    }

    return nil, node.data
}

// AddNode 插入节点
// index 索引位置,插入索引之后
// data 插入内容
func (l *SingleLinkedList) AddNode(index, data int) error {
    if l.IsEmpty() {
        // 链表为空,添加头节点
        return l.AddHead(data)
    } else if l.size == index {
        // 添加尾节点
        return l.AddTail(data)
    } else {
        // 找到需要插入节点
        err, node := l.Node(index)

        if err != nil {
            return err
        }

        newNode := &Node{
            data: data,
            next: node.next,
        }

        node.next = newNode

        l.size = l.size + 1
        return nil
    }
}

// AddHead 添加头节点
func (l *SingleLinkedList) AddHead(data int) error {
    if l.head != nil {
        return errors.New("头节点已经存在")
    }

    l.head = &Node{
        data: data,
        next: nil,
    }

    l.size = 1
    return nil
}

// AddTail 添加尾节点
func (l *SingleLinkedList) AddTail(data int) error {
    err, tail := l.Node(l.size - 1)
    if err != nil {
        return err
    }

    newTail := &Node{
        data: data,
        next: nil,
    }

    tail.next = newTail
    l.size = l.size + 1

    return nil
}

// SetNode 设置节点值
func (l *SingleLinkedList) SetNode(index, data int) error {
    err, node := l.Node(index)
    if err != nil {
        return err
    } else {
        node.data = data
        return nil
    }
}

// IsEmpty 链表是否为空
func (l *SingleLinkedList) IsEmpty() bool {
    return l.size == 0
}

// node 获得节点
func (l *SingleLinkedList) Node(index int) (error, *Node) {
    if l.IsEmpty() {
        return errors.New("empty list"), nil
    }

    if l.isOutSpace(index) {
        return errors.New("下标无效,越界。"), nil
    }

    //  TODO 二分查找

    node := l.head

    for i := 0; i < index; i++ {
        node = node.next
    }

    return nil, node
}

// isOutSpace 是否超出范围
func (l *SingleLinkedList) isOutSpace(index int) bool {
    if l.size < index || index < 0 {
        // 越界
        return true
    }
    return false
}

func (l *SingleLinkedList) isHead(index int) bool {
    return index == 0
}

func (l *SingleLinkedList) isTail(index int) bool {
    return index == l.size-1
}

// del 删除节点
func (l *SingleLinkedList) del(index int) error {
    if l.isHead(index) {
        // 头节点
        err, node := l.Node(index)
        if err != nil {
            return err
        }

        node.next = nil
        return nil
    }

    if l.isTail(index) {
        // 尾节点
        err, node := l.Node(index - 1)
        if err != nil {
            return err
        }

        node.next = nil
        return nil
    }

    err, prev := l.Node(index - 1)
    if err != nil {
        return err
    }
    err, next := l.Node(index + 1)
    if err != nil {
        return err
    }

    prev.next = next

    return nil
}

// ToString
func (l *SingleLinkedList) ToString() string {
    var str = ""
    node := l.head
    var s = strconv.Itoa(node.data)
    str += s + ","

    for i := 0; i < l.size; i++ {
        if node.next != nil {
            node = node.next
            var s = strconv.Itoa(node.data)
            str += s + ","
        }
    }

    return str
}

func main() {
    // 添加节点测试
    // addNodeTest()

    // 超范围测试
    // outSpaceTest()

    // 删除节点
    delNodeTest()
}

func addNodeTest() {
    sll := New()
    // 添加头节点
    sll.AddHead(0)
    // 插入节点
    sll.AddNode(1, 1)
    sll.AddNode(2, 2)
    sll.AddNode(3, 3)
    s := sll.ToString()
    fmt.Println("toString:", s)
}

func outSpaceTest() {
    sll := New()
    // 添加头节点
    sll.AddHead(0)
    err := sll.AddNode(9, 9)
    if err != nil {
        fmt.Println(err)
    }
}

func delNodeTest() {
    sll := New()
    // 添加头节点
    sll.AddHead(0)
    // 插入节点
    sll.AddNode(1, 1)
    sll.AddNode(2, 2)
    sll.AddNode(3, 3)

    sll.del(1)

    s := sll.ToString()
    fmt.Println("toString:", s)
}

相关文章

  • 链表基础

    链表基础 链表长度 链表为空 链表结构 链表增加

  • 双向链表&双向循环链表

    链表分为:单链表、单向循环链表、双向链表、双向循环链表本节主要说明:双向链表、双向循环链表 定义结点 一、双向链表...

  • 算法与数据结构:链表

    链表 链表还分为单向链表和双向链表, 但是这篇文章只说单向链表 , 下次再讲双向链表 . 链表和数组的区别 ? 链...

  • 链表

    链表 单链表反转链表中环的检测两个有序链表合并删除链表倒数第n个节点求链表的元素总个数 一.单向链表 链表共有特征...

  • 五、双向链表

    双向链表 此前介绍的链表,也叫做单向链表使用双向链表可以提升链表的综合性能 修改之前的单链表的源码: 双向链表 –...

  • 链表

    内容 链表数据结构 向链表添加元素 从链表移除元素 使用 LinkedList 表 双向链表 循环链表 链表数据结...

  • 数据与算法结构

    线性表 顺序表 链表(物理上离散,逻辑上连续) 链表的类别 单链表 循环链表 双链表 链表的操作 顺序表与链表的比...

  • 数据结构——链表

    本文所讲的链表是单链表,链表采用无头链表 科普下:一般链表可以分为有头节点的链表与无头节点的链表 有头节点的链表:...

  • 链表

    文章结构 链表的定义 链表的插入和删除操作 链表的特性 常见的链表结构 自定义链表 链表的经典操作 使用链表实现L...

  • Algorithm小白入门 -- 单链表

    单链表递归反转链表k个一组反转链表回文链表 1. 递归反转链表 单链表节点的结构如下: 1.1 递归反转整个单链表...

网友评论

      本文标题:链表

      本文链接:https://www.haomeiwen.com/subject/nijbkdtx.html