golang之单链表和双链表实现

实现单链表、双向链表,增删操作

单链表实现

package linkedList

import "fmt"

/**
*
* 实现单链表(可以完成增,删,查)
* 增加分为:在指定的节点前增加,在指定的节点后增加,在链表的尾部/头部插入节点;
* 删除分为:删除指定的节点;
* Author: sxy
 */

// ps: 对于循环单链表而言,只需要将尾节点指向首节点即可。
type Node struct {
	next *Node
	val  int
}

type LinkedList struct {
	head   *Node
	length int
}

func NewNode(value int) *Node {
	return &Node{next: nil, val: value}
}

func NewLinkedList() *LinkedList {
	return &LinkedList{NewNode(0), 0}
}

func (node *Node) GetNext() *Node {
	return node.next
}

func (node *Node) GetValue() int {
	return node.val
}

// 在指定的节点后面添加
func (linked *LinkedList) InsertNodeAfter(node *Node, value int) bool {
	if node == nil || linked == nil {
		return false
	}

	sourceNext := node.next
	newNode := NewNode(value)
	node.next = newNode
	newNode.next = sourceNext

	linked.length++
	return true
}

// 在某个节点之前添加, 先找到这个节点前面的节点,再创建新的节点插入 到这个节点之前。
func (linked *LinkedList) InsertNodeBefore(node *Node, value int) bool {
	// 不能给头节点前面插入 节点。
	if linked.head == node || node == nil {
		return false
	}
	// 链表的第一个节点
	pre := linked.head
	// 链表的第二个节点
	cur := linked.head.next

	for ; cur != nil; {
		if node == cur {
			break
		}
		pre = cur
		cur = cur.next
	}

	if cur == nil {
		return false
	}

	newNode := NewNode(value)

	pre.next = newNode
	newNode.next = cur
	linked.length++
	return true
}

//  在链表头插入,即是插入到header节点之后
func (linked *LinkedList) InsertNodeHead(value int) bool {
	return linked.InsertNodeAfter(linked.head, value)
}

// 在链表尾部插入,先找到链表的为节点,在插入到这个尾部节点之后
func (linked *LinkedList) InsertNodeTail(value int) bool {
	if linked == nil {
		return false
	}
	node := linked.head
	for node.next != nil {
		node = node.next
	}

	return linked.InsertNodeAfter(node, value)
}

//  根据index拿到指定的节点,如果index为0, 表示拿到的是head, index为1,才拿到的是链表的第一个节点。
func (linked *LinkedList) FindNodeByIndex(index int) (bool, *Node) {
	if linked == nil {
		return false, nil
	}
	if index > linked.length {
		return false, nil
	}

	tmp := linked.head
	for i := 0; i < index; i++ {
		tmp = tmp.next
	}

	return true, tmp
}

// 删除节点,遍历链表,找到删除节点的前置节点,将此节点删除。
func (linked *LinkedList) DeleteNode(deleteNode *Node) bool {

	if linked.head == nil || deleteNode == nil {
		return false
	}

	pre := linked.head
	cur := pre.next
//  如果cur 不为空,且cur!=deleteNode,则继续pre赋值
	for cur != nil {
		if cur == deleteNode {
			break
		}
		pre = cur
		cur = cur.next
	}

	if nil == cur {
		return false
	}

	pre.next = deleteNode.next
	deleteNode = nil
	linked.length--
	return true
}

func (linked *LinkedList)Print(){
	cur := linked.head.next
	format := ""
	for nil != cur {
		format += fmt.Sprintf("%+v", cur.GetValue())
		cur = cur.next
		if nil != cur {
			format += "->"
		}
	}
	fmt.Println(format)
}

测试单链表

package linkedList

import "testing"

func TestInsertToHead(t *testing.T) {
	l := NewLinkedList()
	for i := 0; i < 10; i++ {
		l.InsertNodeHead(i + 1)
	}
	l.Print()
}

func TestInsertToTail(t *testing.T) {
	l := NewLinkedList()
	for i := 0; i < 10; i++ {
		l.InsertNodeTail(i + 1)
	}
	l.Print()
}

func TestFindByIndex(t *testing.T) {
	l := NewLinkedList()
	for i := 0; i < 10; i++ {
		l.InsertNodeTail(i + 1)
	}
	t.Log(l.FindNodeByIndex(0))
	t.Log(l.FindNodeByIndex(9))
	t.Log(l.FindNodeByIndex(10))
	t.Log(l.FindNodeByIndex(11))
}

func TestDeleteNode(t *testing.T) {
	l := NewLinkedList()
	for i := 0; i < 3; i++ {
		l.InsertNodeTail(i + 1)
	}
	l.Print()

	t.Log(l.DeleteNode(l.head.next))
	l.Print()

	t.Log(l.DeleteNode(l.head.next.next))
	l.Print()
}

双链表实现

package linkedList

import "fmt"

/**
*
* 实现双链表(可以完成增,删,查)
* 增加分为:在指定的节点前增加,在指定的节点后增加,在链表的尾部/头部插入节点;
* 删除分为:删除指定的节点;
* Author: sxy
 */

// ps: 对于循环双链表而言,只需要将首节点的pre指针指向尾节点,尾节点的next指针指向首节点即可

type BothNode struct {
	pre  *BothNode
	next *BothNode
	val  int
}

type BothNodeList struct {
	head   *BothNode
	length int
}

func NewBothNode(val int) *BothNode {
	return &BothNode{pre: nil, next: nil, val: val}
}

func (bothnode *BothNode) GetNext() *BothNode {
	return bothnode.next
}

func (bothnode *BothNode) GetPre() *BothNode {
	return bothnode.pre
}

func (bothnode *BothNode) GetValue() int {
	return bothnode.val
}

func NewBothNodeList() *BothNodeList {
	return &BothNodeList{head: NewBothNode(0), length: 0}
}

// 在指定的节点后增加
func (bnl *BothNodeList) InsertBothNodeAfter(node *BothNode, val int) bool {
	if bnl == nil || node == nil {
		return false
	}

	newBothNode := NewBothNode(val)

	tmpNext := node.next

	node.next = newBothNode
	newBothNode.pre = node
	newBothNode.next = tmpNext

	bnl.length++
	return true
}

// 在链表的头部添加
func (bnl *BothNodeList) InsertBothNodeHeader(val int) bool {
	if bnl == nil {
		return false
	}
	return bnl.InsertBothNodeAfter(bnl.head, val)
}

// 在链表的尾部添加
// 需要先找到尾部节点
func (bnl *BothNodeList) InsertBothNodeTail(val int) bool {
	if bnl == nil {
		return false
	}
	current := bnl.head
	for current.next != nil {
		current = current.next
	}

	return bnl.InsertBothNodeAfter(current, val)
}

// 在指定节点之前添加
// 需要先找到此节点的前置节点
func (bnl *BothNodeList) InsertBothNodeBefore(bothNode *BothNode, val int) bool {
	if bnl == nil || bothNode == nil {
		return false
	}
	pre := bnl.head
	cur := pre.next
	for ; pre.next != nil; {
		// pre 即是cur的前置节点, cur即是当前节点
		if cur == bothNode {
			break
		}
		pre = cur
		cur = pre.next
	}

	if cur == nil {
		return false
	}

	newBothNode := NewBothNode(val)

	tmpNext := pre.next
	pre.next = newBothNode
	newBothNode.pre = pre
	newBothNode.next = tmpNext
	tmpNext.pre = newBothNode
	bnl.length++
	return true
}

// 删除某个节点
// 需要先找到要删除的节点
func (bnl *BothNodeList) DeleteBothNode(bothNode *BothNode) bool {
	if bnl == nil || bothNode == nil {
		return false
	}

	pre := bnl.head
	cur := pre.next
	for ; cur != nil; {
		if cur == bothNode {
			break
		}
		pre = cur
		cur = pre.next
	}
	if cur == nil {
		return false
	}

	//  真正的删除操作
	tmpNextBothNode := bothNode.next
	pre.next = tmpNextBothNode
	bnl.length--
	return true
}

//  根据index拿到指定的节点
func (bnl *BothNodeList) GetBothNodeByIndex(index int) (bool, *BothNode) {
	if bnl == nil || bnl.length == 0 || bnl.length < index {
		return false, nil
	}
	pre := bnl.head
	for i := 0; i < index; i++ {
		pre=pre.next
	}

	return true, pre
}


func (bnl *BothNodeList)Print(){
	cur :=bnl.head.next
	format := ""
	for nil != cur {
		format += fmt.Sprintf("%+v", cur.GetValue())
		cur = cur.next
		if nil != cur {
			format += "->"
		}
	}
	fmt.Println(format)
}

测试

package linkedList

import "testing"

func TestInsertBothNodeHeader(t *testing.T) {
	l := NewBothNodeList()
	for i := 0; i < 10; i++ {
		l.InsertBothNodeHeader(i + 1)
	}
	l.Print()
}

func TestInsertBothNodeTail(t *testing.T) {
	l := NewBothNodeList()
	for i := 0; i < 10; i++ {
		l.InsertBothNodeTail(i + 1)
	}
	l.Print()
}

func TestGetBothNodeByIndex(t *testing.T) {
	l := NewBothNodeList()
	for i := 0; i < 10; i++ {
		l.InsertBothNodeTail(i + 1)
	}
	t.Log(l.GetBothNodeByIndex(0))
	t.Log(l.GetBothNodeByIndex(9))
	t.Log(l.GetBothNodeByIndex(10))
	t.Log(l.GetBothNodeByIndex(11))
}

func TestDeleteBothNode(t *testing.T) {
	l := NewBothNodeList()
	for i := 0; i < 3; i++ {
		l.InsertBothNodeTail(i + 1)
	}
	l.Print()

	t.Log(l.DeleteBothNode(l.head.next))
	l.Print()

	t.Log(l.DeleteBothNode(l.head.next.next))
	l.Print()
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值