【Go】单链表
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】单链表的更多相关文章
- 时间复杂度分别为 O(n)和 O(1)的删除单链表结点的方法
有一个单链表,提供了头指针和一个结点指针,设计一个函数,在 O(1)时间内删除该结点指针指向的结点. 众所周知,链表无法随机存储,只能从头到尾去遍历整个链表,遇到目标节点之后删除之,这是最常规的思路和 ...
- 单链表的C++实现(采用模板类)
采用模板类实现的好处是,不用拘泥于特定的数据类型.就像活字印刷术,制定好模板,就可以批量印刷,比手抄要强多少倍! 此处不具体介绍泛型编程,还是着重叙述链表的定义和相关操作. 链表结构定义 定义单链表 ...
- Java实现单链表的各种操作
Java实现单链表的各种操作 主要内容:1.单链表的基本操作 2.删除重复数据 3.找到倒数第k个元素 4.实现链表的反转 5.从尾到头输出链表 6.找到中间节点 7.检测链表是否有环 8.在 ...
- [LeetCode] Linked List Cycle II 单链表中的环之二
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...
- c++单链表基本功能
head_LinkNode.h /*单链表类的头文件*/#include<assert.h>#include"compare.h"typedef int status; ...
- 单链表、循环链表的JS实现
数据结构系列前言: 数据结构作为程序员的基本知识,需要我们每个人牢牢掌握.近期我也展开了对数据结构的二次学习,来弥补当年挖的坑...... 当时上课的时候也就是跟着听课,没有亲自实现任何一种数据结 ...
- C代码实现非循环单链表
C代码实现非循环单链表, 直接上代码. # include <stdio.h> # include <stdlib.h> # include <malloc.h> ...
- 分离的思想结合单链表实现级联组件:CascadeView
本文介绍自己最近做省市级联的类似的级联功能的实现思路,为了尽可能地做到职责分离跟表现与行为分离,这个功能拆分成了2个组件并用到了单链表来实现关键的级联逻辑,下一段有演示效果的gif图.虽然这是个很常见 ...
- 数据结构:单链表结构字符串(python版)添加了三个新功能
#!/urs/bin/env python # -*- coding:utf-8 -*- #异常类 class stringTypeError(TypeError): pass #节点类 class ...
- 数据结构:单链表结构字符串(python版)改进
此篇文章的replace实现了字符串类的多次匹配,但依然有些不足. 因为python字符串对象为不变对象,所以replace方法并不修改原先的字符串,而是返回修改后的字符串. 而此字符串对象时用单链表 ...
随机推荐
- .Net Core in Docker极简入门(下篇)
Tips:本篇已加入系列文章阅读目录,可点击查看更多相关文章. 目录 前言 开始 Docker-Compose 代码修改 yml file up & down 镜像仓库 最后 前言 上一篇[. ...
- ngx lua获取时间戳的几种方式
原创自由de单车 最后发布于2017-02-14 14:58:43 阅读数 18218 收藏 在ngx_lua里,获取时间相关信息的方式大概有4种(见下面代码): print(string.forma ...
- JAVA基础1(语法)
一.标识符和关键字 在程序中用于定义名称的都为标识符,如文件名称.类名称.方法名称或变量名称等. 在Java中标识符的定义格式由字母.数字._(下划线),$所组成,其中不能重复,不能以数字开头,不能是 ...
- jquery判断radio是否选中
微交易-实体系统 微交易-虚拟系统 <div class="system"> <div class="systemt"> <l ...
- PHP array_diff_ukey() 函数
实例 比较两个数组的键名(使用用户自定义函数比较键名),并返回差集: <?phpfunction myfunction($a,$b){if ($a===$b){return 0;}return ...
- Python基础教程 (第2+3 版)打包pdf|内附网盘链接提取码
<Python基础教程 第3版>包括Python程序设计的方方面面:首先,从Python的安装开始,随后介绍了Python的基础知识和基本概念,包括列表.元组.字符 ...
- “商家参数格式有误”应用切微信H5支付完美解决方案
一.业务场景发生 最近在跟一些合作公司作业务对接,在对方的APP中接入我们的H5支付,包括微信和支付宝. 那就开搞,进展顺利,貌似一切都在掌握之中,给到对方一个链接即可调起支付.形如: https:/ ...
- python数据可视化编程实战PDF高清电子书
点击获取提取码:3l5m 内容简介 <Python数据可视化编程实战>是一本使用Python实现数据可视化编程的实战指南,介绍了如何使用Python最流行的库,通过60余种方法创建美观的数 ...
- 精通python网络爬虫PDF高清完整版免费下载|百度云盘|Python基础教程免费电子书
点击获取书籍提取码:yc9w
- Spring的事务抽象
Spring提供了一致的事务管理抽象,该抽象能实现为不同的事务API提供一致的编程模型.无视我们使用jdbc.hibernate.mybatis哪种方式来操作数据,无视事务是jta事务还是jdbc事务 ...