node.go

// 链表节点
type Node struct {
data interface{}
next *Node
} // 构造一个节点
func NewNode(data interface{}) *Node {
return &Node{data: data, next: nil}
}

list.go

package single_linked_list

import (
"fmt"
) type SingleLinked interface {
Add(node *Node) // 在链表前面插入节点
Append(node *Node) // 在链表后面插入节点
Delete(node *Node) // 删除节点
DeleteByIndex(index int) // 根据索引删除节点
InsertBefore(data interface{}, node *Node) // 在xx之前插入节点
InsertAfter(data interface{}, node *Node) // 在xx之后插入节点
Get(index int) interface{}
Length() int
String() string
Reverse() // 反转链表
} type List struct {
head *Node // 链表头结点
length int // 链表长度
} func NewList() *List {
head := NewNode(nil)
return &List{head: head, length: 0}
} // 在链表前面插入节点
func (list *List) Add(node *Node) {
if list.head == nil {
list.head.next = node
node.next = nil
list.length++
} else {
temp := list.head // 保存头结点
node.next = temp.next // 新节点指向的节点就是原先头结点指向的节点
temp.next = node // 头结点指向新节点
list.length++
}
} // 在链表后面插入节点
func (list *List) Append(node *Node) {
if list.head == nil {
list.head.next = node
node.next = nil
list.length++
} else {
temp := list.head
for temp.next != nil { // 一直循环到链表最后一个节点
temp = temp.next
}
temp.next = node
list.length++
}
} // 在xx之前插入节点
func (list *List) InsertBefore(data interface{}, node *Node) {
temp := list.head
isFind := false
for temp.next != nil {
if temp.next.data == data { // 根据data找到其节点,在该节点之前插入新节点
isFind = true
break
}
temp = temp.next
}
if isFind {
node.next = temp.next
temp.next = node
list.length++
}
} // 在xx之后插入节点
func (list *List) InsertAfter(data interface{}, node *Node) {
temp := list.head
isFind := false
for temp.next != nil {
if temp.data == data {
isFind = true
break
}
temp = temp.next
}
if isFind {
node.next = temp.next
temp.next = node
list.length++
}
} // 删除节点
func (list *List) Delete(node *Node) {
if node == nil {
return
}
temp := list.head
// 如果下一个节点不等于要删除的节点,则循环找下去
for temp.next != nil && temp.next != node {
temp = temp.next
}
if temp.next == node {
// temp指向 要删除节点指向 的节点
temp.next = temp.next.next
list.length--
}
} // 根据索引删除节点
func (list *List) DeleteByIndex(index int) {
if index > list.length-1 || index < 0 {
return
}
temp := list.head
for index > 0 {
temp = temp.next
index--
}
temp.next = temp.next.next
list.length--
} func (list *List) Get(index int) interface{} {
if index > list.length-1 || index < 0 {
return nil
}
temp := list.head
for index > -1 {
temp = temp.next
index--
}
return temp.data
} func (list *List) Length() int {
return list.length
} // 打印链表
func (list *List) String() string {
var str string
node := list.head
for node.next != nil {
str += fmt.Sprintf("%v-->", node.next.data)
node = node.next
}
str = fmt.Sprintf("head-->%snil", str)
return str
} // 反转链表
func (list *List) Reverse() {
// 链表为空或只有1个节点
if list.head == nil || list.head.next == nil {
return
} else {
/*
------ ------ ------
head.next -> 0x01| | 0x02| | 0x03| |
| aa | ' | bb | ' | cc |
| | ' | | ' | |
| 0x02 | ' | 0x03 | ' | nil |
------ ------ ------ ------ ------ ------
| |0x01 | |0x02 | |0x03 <- head.next
| aa | ' | bb | ' | cc |
| | ' | | ' | |
| nil | ' | 0x01 | ' | 0x02 |
------ ------ ------
*/
// prev ----> curr ----> currNext
var prev *Node // 前一个节点(初始时即为 空节点)
var curr *Node = list.head.next // 当前节点(初始时即为 第1个节点)
for curr != nil {
currNext := curr.next // 暂存当前节点的下一个节点(初始时即为 第2个节点)
curr.next = prev // 当前节点指向前一个节点(初始时即让 第1个节点指向空节点;... 那么 1 <- 2 2 <- 3)
// 持续推进(循环到最后)
prev = curr // 前一个节点变成了当前节点(初始时理解为 第1个节点跑到空节点位置)
curr = currNext // 当前节点变成了下一个节点(初始时理解为 第2个节点跑到第1个节点位置)
}
list.head.next = prev
}
}

main.go

// 单链表
func main() {
var list single_linked_list.SingleLinked = single_linked_list.NewList()
n1 := single_linked_list.NewNode(1)
n2 := single_linked_list.NewNode(2)
n3 := single_linked_list.NewNode(3)
n4 := single_linked_list.NewNode(4)
n5 := single_linked_list.NewNode(5)
list.Add(n1)
list.Add(n2)
list.Add(n3)
list.Append(n4)
list.Append(n5)
fmt.Println(list) // head-->3-->2-->1-->4-->5-->nil
list.Delete(n1)
fmt.Println(list) // head-->3-->2-->4-->5-->nil
list.DeleteByIndex(2)
fmt.Println(list) // head-->3-->2-->5-->nil
list.InsertBefore(2, n1)
fmt.Println(list) // head-->3-->1-->2-->5-->nil
list.InsertAfter(2, n4)
fmt.Println(list) // head-->3-->1-->2-->4-->5-->nil
fmt.Println(list.Length()) // 5
fmt.Println(list.Get(0)) // 3
fmt.Println(list.Get(10)) // nil
list.Reverse()
fmt.Println(list) // head-->5-->4-->2-->1-->3-->nil
}

【Go】单链表的更多相关文章

  1. 时间复杂度分别为 O(n)和 O(1)的删除单链表结点的方法

    有一个单链表,提供了头指针和一个结点指针,设计一个函数,在 O(1)时间内删除该结点指针指向的结点. 众所周知,链表无法随机存储,只能从头到尾去遍历整个链表,遇到目标节点之后删除之,这是最常规的思路和 ...

  2. 单链表的C++实现(采用模板类)

    采用模板类实现的好处是,不用拘泥于特定的数据类型.就像活字印刷术,制定好模板,就可以批量印刷,比手抄要强多少倍! 此处不具体介绍泛型编程,还是着重叙述链表的定义和相关操作.  链表结构定义 定义单链表 ...

  3. Java实现单链表的各种操作

    Java实现单链表的各种操作 主要内容:1.单链表的基本操作 2.删除重复数据 3.找到倒数第k个元素   4.实现链表的反转   5.从尾到头输出链表 6.找到中间节点 7.检测链表是否有环 8.在 ...

  4. [LeetCode] Linked List Cycle II 单链表中的环之二

    Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...

  5. c++单链表基本功能

    head_LinkNode.h /*单链表类的头文件*/#include<assert.h>#include"compare.h"typedef int status; ...

  6. 单链表、循环链表的JS实现

    数据结构系列前言: 数据结构作为程序员的基本知识,需要我们每个人牢牢掌握.近期我也展开了对数据结构的二次学习,来弥补当年挖的坑......   当时上课的时候也就是跟着听课,没有亲自实现任何一种数据结 ...

  7. C代码实现非循环单链表

    C代码实现非循环单链表, 直接上代码. # include <stdio.h> # include <stdlib.h> # include <malloc.h> ...

  8. 分离的思想结合单链表实现级联组件:CascadeView

    本文介绍自己最近做省市级联的类似的级联功能的实现思路,为了尽可能地做到职责分离跟表现与行为分离,这个功能拆分成了2个组件并用到了单链表来实现关键的级联逻辑,下一段有演示效果的gif图.虽然这是个很常见 ...

  9. 数据结构:单链表结构字符串(python版)添加了三个新功能

    #!/urs/bin/env python # -*- coding:utf-8 -*- #异常类 class stringTypeError(TypeError): pass #节点类 class ...

  10. 数据结构:单链表结构字符串(python版)改进

    此篇文章的replace实现了字符串类的多次匹配,但依然有些不足. 因为python字符串对象为不变对象,所以replace方法并不修改原先的字符串,而是返回修改后的字符串. 而此字符串对象时用单链表 ...

随机推荐

  1. MacOS下JDK8的安装与配置

    微信搜索"艺术行者",关注并回复关键词"jdk8"获取安装包和API文档资料! 一.安装环节 1.打开网页 https://www.oracle.com/jav ...

  2. PHP fileatime() 函数

    定义和用法 fileatime() 函数返回指定文件的上次访问时间. 如果成功,该函数将以 Unix 时间戳形式返回文件的上次访问时间.如果失败,则返回 FALSE. 语法 fileatime(fil ...

  3. luogu P4095 [HEOI2013]Eden 的新背包问题 多重背包 背包的合并

    LINK:Eden 的新背包问题 就是一个多重背包 每次去掉一个物品 询问钱数为w所能买到的最大值. 可以对于每次Q暴力dp 利用单调队列优化多重背包 这样复杂度是Qnm的. 发现过不了n==10的点 ...

  4. luogu P2973 [USACO10HOL]Driving Out the Piggies G 驱逐猪猡

    luogu LINK:驱逐猪猡 bzoj LINK:猪猪快跑 问题是在1时刻有个炸蛋在1号点 这个炸弹有p/q的概率爆炸 如果没有爆炸 那么会有1/di的概率选择一条边跳到另外一个点上重复这个过程. ...

  5. 从别人的代码中学习golang系列--03

    这篇博客还是整理从https://github.com/LyricTian/gin-admin 这个项目中学习的golang相关知识. 作者在项目中使用了 github.com/casbin/casb ...

  6. JsLint undeclared ‘window’

    如果使用IDEA 设置一下 globals 或 /*global window */ ... your script goes here https://stackoverflow.com/quest ...

  7. 41-native关键字的理解

    使用 native 关键字说明这个方法是原生函数,也就是这个方法是用 C/C++等非Java 语言实现的,并且被编译成了 DLL,由 java 去调用. (1)为什么要用 native 方法 java ...

  8. SAFe必备——提高团队敏捷性

    规模化敏捷之于项目群,就像Scrum之于敏捷团队.为了创建高质量业务解决方案,企业需要提高自身能力,提升团队和技术敏捷性,实现真正的规模化敏捷. 敏捷发布火车 实现团队和技术敏捷性,首先需要敏捷团队围 ...

  9. Xcode11更改启动页设置方法

    新开了个项目,发现之前的启动页怎么也调不好,后来发现配置里边少了一行,所以整理一下,我使用的xcode版本是11. 以前的时候是在这2个中间,还有一行,通过下边2项来配置,现在更改了,附上新的教程.如 ...

  10. /usr/bin/docker-current: Error response from daemon: driver failed programming external connectivity on endpoint naughty_wozniak (444e26e0a2a3adb1ff88177ead86099ad64c0406afcec179ce7cfeef8ffa2d5c): (i

    /usr/bin/docker-current: Error response from daemon: driver failed programming external connectivity ...