实现单链表、双向链表,增删操作
单链表实现
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()
}