【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方法并不修改原先的字符串,而是返回修改后的字符串. 而此字符串对象时用单链表 ...
随机推荐
- three.js之初探骨骼动画
今后的几篇郭先生主要说说three.js骨骼动画.three.js骨骼动画十分有意思,但是对于初学者来说,学起来要稍微困难一些,官方文档比较少,网上除了用圆柱体的例子就是引用外部模型的,想要熟练使用骨 ...
- PHP debug_zval_dump() 函数
debug_zval_dump 函数用于查看一个变量在zend引擎中的引用计数.类型信息. 版本要求:PHP 4 >= 4.2.0, PHP 5, PHP 7高佣联盟 www.cgewang.c ...
- CF724C Ray Tracing 扩展欧几里得 平面展开
LINK:Ray Tracing 虚这道题很久了 模拟赛考了一个加强版的 瞬间就想到了这道简化版的. 考虑做法 暴力模拟可能可以 官方正解好像就是这个. 不过遇到这种平面问题可以考虑把平面给无限的展开 ...
- Spring 参数注入
一个(类)Bean可能包含多种属性,这些属性怎么配置??? 见下: 用People Dog Cat Tiger Panda五个类来学习一些常用的=_= 重点在XML <!--基本类型注入- ...
- 【Java并发知识点汇总】
1,ArrayList 为什么线程不安全(https://www.jianshu.com/p/41be1efe5d65)
- 【SCOI2008】奖励关 题解(状压DP+期望)
题目链接 题目大意:给定$n$个宝物,每次随机抛出一个宝物,奖励分数为$p_i$.但如果选这个宝物必须选过它的前置宝物集合.共进行$K$轮问最优策略下的期望. $n\leq 15,-10^6\leq ...
- Qt自定义控件之仪表盘3--雷达扫描图
1.设计思想 雷达扫描图,在影视作品中见到较多,比如飞机雷达.舰艇雷达,有一个扫描线转圈代表雷达一周旋转或一个批次的收发,发现目标就在表盘上标记位置.和汽车仪表盘类似,汽车仪表盘有底盘背景图.同圆.刻 ...
- Python生成测试数据-Faker(非LOL选手-李相赫)
Faker介绍 官方文档:https://faker.readthedocs.io/en/master/ Faker is a Python package that generates fake d ...
- 00-java语言概述
1.基础常识软件:即一系列按照特定顺序组织的计算机数据和指令的集合.分为:系统软件 和 应用软件 系统软件:windows , mac os , linux ,unix,android,ios,... ...
- python3.1for循环及应用
#给定范围,进行循环for i in range (0,5): print(i) #对序列进行遍历list1=[1,2,3,4,5]for i in list1: print(i+1) #对元组进行遍 ...