双向链表比起单向链表,

多了一个向前指向的指针,

所以在增删查改时,要同时照顾到两个指针的指向。

DoublyLinkedList.go
package DoublyLinkedList

//双向链表
type Node struct {
	data int
	next *Node
	prev *Node
}

type DoublyLinkedList struct {
	head *Node
	tail *Node
}

func (list *DoublyLinkedList) InsertFirst(i int) {
	data := &Node{data: i}
	if list.head != nil {
		list.head.prev = data
		data.next = list.head
	}
	list.head = data
}

func (list *DoublyLinkedList) InsertLast(i int) {
	data := &Node{data: i}
	if list.head == nil {
		list.head = data
		list.tail = data
		return
	}
	if list.tail != nil {
		list.tail.next = data
		data.prev = list.tail
	}
	list.tail = data
}

func (list *DoublyLinkedList) RemoveByValue(i int) bool {
	if list.head == nil {
		return false
	}

	if list.head.data == i {
		list.head = list.head.next
		list.head.prev = nil
		return true
	}
	if list.tail.data == i {
		list.tail = list.tail.prev
		list.tail.next = nil
		return true
	}
	current := list.head
	for current.next != nil {
		if current.next.data == i {
			if current.next.next != nil {
				current.next.next.prev = current
			}
			current.next = current.next.next
			return true
		}
		current = current.next
	}
	return false
}

func (list *DoublyLinkedList) RemoveByIndex(i int) bool {
	if list.head == nil {
		return false
	}
	if i < 0 {
		return false
	}

	if i == 0 {
		list.head.prev = nil
		list.head = list.head.next
		return true
	}
	current := list.head
	for u := 1; u < i; u++ {
		if current.next.next == nil {
			return false
		}
		current = current.next
	}
	if current.next.next != nil {
		current.next.next.prev = current
	}
	current.next = current.next.next
	return true
}

func (list *DoublyLinkedList) SearchValue(i int) bool {
	if list.head == nil {
		return false
	}
	current := list.head
	for current != nil {
		if current.data == i {
			return true
		}
		current = current.next
	}
	return false
}

func (list *DoublyLinkedList) GetFirst() (int, bool) {
	if list.head == nil {
		return 0, false
	}
	return list.head.data, true
}

func (list *DoublyLinkedList) GetLast() (int, bool) {
	if list.head == nil {
		return 0, false
	}
	current := list.head
	for current.next != nil {
		current = current.next
	}
	return current.data, true
}

func (list *DoublyLinkedList) GetSize() int {
	count := 0
	current := list.head
	for current != nil {
		count += 1
		current = current.next
	}
	return count
}

func (list *DoublyLinkedList) GetItemFromStart() []int {
	var items []int
	current := list.head
	for current != nil {
		items = append(items, current.data)
		current = current.next
	}
	return items
}

func (list *DoublyLinkedList) GetItemFromEnd() []int {
	var items []int
	current := list.tail
	for current != nil {
		items = append(items, current.data)
		current = current.prev
	}
	return items
}

  

DoublyLinkedList_test.go
package DoublyLinkedList

//使用随机数作测试
import (
	"fmt"
	"math/rand"
	"testing"
	"time"
)

func TestDoublyLinkedList(t *testing.T) {

	random := rand.New(rand.NewSource(time.Now().UnixNano()))
	headNode := &Node{
		data: random.Intn(100),
		next: nil,
		prev: nil,
	}
	list := &DoublyLinkedList{
		head: headNode,
		tail: headNode,
	}

	fmt.Println(list.GetItemFromStart())
	list.InsertFirst(random.Intn(100))
	fmt.Println(list.GetItemFromStart())
	list.InsertLast(random.Intn(100))
	fmt.Println(list.GetItemFromStart())
	randNumber := random.Intn(100)
	list.InsertFirst(randNumber)
	fmt.Println(list.GetItemFromStart())
	list.InsertLast(random.Intn(100))
	fmt.Println(list.GetItemFromStart())
	list.InsertFirst(random.Intn(100))
	fmt.Println(list.GetItemFromStart())
	fmt.Println(list.GetItemFromEnd())

	if list.SearchValue(randNumber) == false {
		t.Fail()
	}
	list.RemoveByValue(randNumber)
	if list.SearchValue(randNumber) == true {
		t.Fail()
	}
	fmt.Println(list.GetFirst())
	fmt.Println(list.GetLast())
	fmt.Println(list.GetSize())

}

  

golang数据结构和算法之DoublyLinkedList双向链表的更多相关文章

  1. golang数据结构和算法之BinarySearch二分查找法

    基础语法差不多了, 就需要系统的撸一下数据结构和算法了. 没找到合适的书, 就参考github项目: https://github.com/floyernick/Data-Structures-and ...

  2. 数据结构与算法-python描述-双向链表

    # coding:utf-8 # 双向链表的相关操作: # is_empty() 链表是否为空 # length() 链表长度 # travel() 遍历链表 # add(item) 链表头部添加 # ...

  3. golang数据结构和算法之QueueLinkedList链表队列

    队列和堆栈不一样的地方在于进出顺序: 堆栈是后进先出, 队列是先进先出. QueueLinkedList.go package QueueLinkedList type Node struct { d ...

  4. golang数据结构和算法之StackLinkedList链表堆栈

    会了上一个,这个就差不离了. StackLinkedList.go package StackLinkedList type Node struct { data int next *Node } t ...

  5. golang数据结构和算法之StackArray数组堆栈

    用数组实现的堆栈, 另一种,是用链表实现的堆栈, 在各种不同的编程语言上, 实现都是类似的. StackArray.go package StackArray //基于数组实现的堆栈 const ar ...

  6. golang数据结构和算法之LinkedList链表

    差不多自己看懂了,可以自己写测试了.:) LinkedList.go package LinkedList //"fmt" type Node struct { data int ...

  7. golang数据结构和算法之CircularBuffer环形缓冲队列

    慢慢练语法和思路, 想说的都在代码及注释里. CircularBuffer package CircularBuffer const arraySize = 10 type CircularBuffe ...

  8. 数据结构与算法 Big O 备忘录与现实

    不论今天的计算机技术变化,新技术的出现,所有都是来自数据结构与算法基础.我们需要温故而知新.        算法.架构.策略.机器学习之间的关系.在过往和技术人员交流时,很多人对算法和架构之间的关系感 ...

  9. 数据结构和算法(Golang实现)(15)常见数据结构-列表

    列表 一.列表 List 我们又经常听到列表 List数据结构,其实这只是更宏观的统称,表示存放数据的队列. 列表List:存放数据,数据按顺序排列,可以依次入队和出队,有序号关系,可以取出某序号的数 ...

随机推荐

  1. LInux:服务的管理-systemctl

    使用systemctl管理服务 服务的启动与停止 服务的启动与停止 命令格式:systemctl 选项 服务名 选项说明: start:启动;stop:停止:restart:重启:status:服务状 ...

  2. java8-04-初识函数式接口

    为什么用函数式接口                                   在函数式编程思想下,允许函数本身作为参数传入另一个函数.使用函数式接口实现"传递行为"的思想 ...

  3. 【2019.10.7 CCF-CSP-2019模拟赛 T2】绝对值(abs)(线段树细节题)

    找规律 设\(p_i=a_{i+1}-a_i\),则答案就是\(\sum_{i=1}^{n-1}p_i\). 考虑若将\(a_i\)加上\(x\)(边界情况特殊考虑),就相当于是将\(p_{i-1}\ ...

  4. Python解释器和Python集成环境小结

    目录 一.执行Python程序的两种方式 1.1 交互式 1.2 命令行式 二.执行Python程序的两种IDE 2.1 Pycharm 2.2 Jupyter 一.执行Python程序的两种方式 1 ...

  5. ROS下多雷达融合算法

    有些小车车身比较长,如果是一个激光雷达,顾前不顾后,有比较大的视野盲区,这对小车导航定位避障来说都是一个问题,比如AGV小车, 所有想在小车前后各加一个雷达,那问题是ROS的建图或者定位导航都只是支持 ...

  6. Python之基本运算符

    基本运算符 1.算符运算符 运算符 描述 例子 + 两个对象相加 a+b - 两个对象相减 a-b * 两个数相乘或返回一个被重复若干次的字符串 a*b / 两个数相除 a/b % 取模,返回除法的余 ...

  7. 【踩坑系列】VS2019提示 ' the package could not be found in c\users\username\nuget\packages\. '

    解决步骤 1.删除对应项目下的 obj 文件夹 2.重新生成该项目

  8. js键盘事件以及键盘事件拦截

    一.键盘事件 onkeydown: 按下键盘时触发 onkeypress: 按下有值的键时触发 注意: onkeypress按下 Ctrl.Alt.Shift.Meta 这样无值的键,这个事件不会触发 ...

  9. MySQL学习——约束

    MySQL学习——约束 摘要:本文主要学习了数据库的约束. primary key(主键) 定义 主键约束是一个列或者多个列,其值能唯一地标识表中的每一行.这样的一列或多列称为表的主键,通过它可以强制 ...

  10. C++ 运算符重载的基本概念

    01 运算符重载的需求 C++ 预定义的运算符,只能用于基本数据类型的运算:整型.实型.字符型.逻辑型等等,且不能用于对象的运算.但是我们有时候又很需要在对象之间能用运算符,那么这时我们就要重载运算符 ...