1. 程式人生 > 其它 >go 連結串列操作

go 連結串列操作

連結串列的特點和初始化

連結串列的特點

用一組任意的儲存單元儲存線性表的資料元素(這組儲存單元可以是連續的,也可以是不連續的)

結點

結點(node)

資料域 => 儲存元素資訊
指標域 => 儲存結點的直接後繼,也稱作指標或鏈

首元結點 是指連結串列中儲存的第一個資料元素的結點
頭結點 是在首元結點之前附設的一個結點,其指標域指向首元結點(非必須)
頭指標 是指向連結串列中第一個結點的指標

單鏈表特點

  • 每個結點中只包含一個指標域
  • 單鏈表是非隨機存取的儲存結構,要取得第i個數據元素必須從頭指標出發,順鏈進行尋找,也稱為順序存取的存取結構

官方包連結串列操作

https://pkg.go.dev/container/list

手動實現單鏈表部分操作

// 實現單鏈表一些基礎操作
package main

import (
	"errors"
	"fmt"
)

// 連結串列結構
type ListNode struct {
	Data int
	Next *ListNode
}

// 初始化連結串列頭,下面所有操作都基於帶頭連結串列
func NewListNode() *ListNode {
	return &ListNode{Next: nil}
}

// 獲取連結串列長度
func (l *ListNode) Length() int {
	len := 0
	for l.Next != nil {
		len++
		l = l.Next
	}
	return len
}

// 插入節點
func (l *ListNode) InsertNode(d int) error {
	newNode := new(ListNode)
	newNode.Data = d
	newNode.Next = l.Next
	l.Next = newNode
	return nil
}

// 刪除節點
func (l *ListNode) DelNode(d int) {
	if l == nil {
		errors.New("Empty List!")
		return
	}
	for l.Next != nil {
		if l.Next.Data == d {
			l.Next = l.Next.Next
			// return 是否全部刪除與d相同資料
		}
		l = l.Next
	}
}

// 遍歷單鏈表
func (l *ListNode) ListNode() {
	for l.Next != nil {
		fmt.Printf("%d", l.Next.Data)
		l = l.Next
	}
}

// 遞迴反轉單鏈表
func ReverseList(pHead, node *ListNode) *ListNode {
	if node.Next == nil {
		pHead.Next = node
		return node
	}

	if n := ReverseList(pHead, node.Next); n != nil {
		n.Next = node
		node.Next = nil
	}

	return node
}

// 遍歷反轉單鏈表
func (pHead *ListNode) ReverseListV2() {
	pReverseHead := pHead
	var pNode = pHead.Next
	var pPrev *ListNode
	for pNode != nil {
		pNext := pNode.Next
		if pNext == nil {
			pReverseHead.Next = pNode
		}
		pNode.Next = pPrev
		pPrev = pNode
		pNode = pNext
	}
	return
}