Go數據結構之鏈表


一:鏈表介紹

鏈表是有序的列表,但在內存的分部較為特殊

二:單鏈表的舉例使用

package main

import (
    "fmt"
)

type Students struct{
    num int
    name string
    next *Students
}

//尾部添加
func InsertStudentNode1(head *Students, student *Students){
    //設置從頭部開始遍歷
    temp := head
    for {
        if temp.next == nil {
            break
        }
        temp = temp.next
    }
    temp.next=student

}
//有序添加
func InsertStudentNode2(head *Students, student *Students){
    temp := head
    for {
        if temp.next == nil {
            break
        }else if temp.next.num > student.num {//按照有小到大添加
            break
        }else if temp.next.num == student.num {
            fmt.Println("節點已存在")
            return
        }
        temp = temp.next
    }

    student.next = temp.next
    temp.next = student

}
//顯示所有節點
func ShowStudentNode(head *Students){
    //設置從頭部開始遍歷
    show := head
    //先判斷是否為空鏈表
    if show.next == nil {
        fmt.Println("鏈表為空")
        return
    }
    for {
        if show.next == nil {
            break
        }
        fmt.Printf("學生編號:%v,姓名:%v\n", show.next.num, show.next.name)
        show = show.next
    }
}
//刪除節點
func DelStudentNode(head *Students, num int){
    temp := head
    if temp.next == nil {
        fmt.Println("鏈表為空")
        return
    }
    for {
        if temp.next.num == num {
            break
        }else if temp.next == nil {
            fmt.Println("節點不存在")
            return
        }
        temp = temp.next
    }

    temp.next = temp.next.next
}
func main() {
    //初始化一個頭結點
    head := &Students{}
    //添加新節點
    student1 := &Students{
        num : 1,
        name : "james",
    }
    student2 := &Students{
        num : 2,
        name : "kobe",
    }
    student5 := &Students{
        num : 5,
        name : "jorden",
    }
    student3 := &Students{
        num : 3,
        name : "shark",
    }
    // 添加節點
    InsertStudentNode1(head, student1)
    InsertStudentNode1(head, student2)
    InsertStudentNode1(head, student5)
    InsertStudentNode2(head, student3)
    //獲取
    ShowStudentNode(head)
    //刪除編號為5的學生
    DelStudentNode(head, 1)
    fmt.Println("刪除后----------------")
    //獲取
    ShowStudentNode(head)
} 結果 [ `go run chainTable.go` | done ]
    學生編號:1,姓名:james
    學生編號:2,姓名:kobe
    學生編號:3,姓名:shark
    學生編號:5,姓名:jorden
    刪除后----------------
    學生編號:2,姓名:kobe
    學生編號:3,姓名:shark
    學生編號:5,姓名:jorden

 三:雙向鏈表

①:雙線鏈表的優點

  ①-1:單向鏈表的查找方向只能向后查找,而雙線鏈表可以向后也可以向前;

  ①-2:單向鏈表不能自我刪除,需要其他節點的協助,而雙線鏈表可以自我刪除(根據指向的前節點與指向的后節點)

②:舉例說明

package main

import (
	"fmt"
)

type Students struct{
	num int
	name string
	pre *Students
	next *Students
}

//尾部添加
func InsertStudentNode1(head *Students, student *Students){
	//設置從頭部開始遍歷
	temp := head
	for {
		if temp.next == nil {
			break
		}
		temp = temp.next
	}
	temp.next=student
	student.pre = temp

}
//有序添加
func InsertStudentNode2(head *Students, student *Students){
	temp := head
	last := false
	for {
		if temp.next == nil {
			last = true
			break
		}else if temp.next.num > student.num {//按照有小到大添加
			break
		}else if temp.next.num == student.num {
			fmt.Println("節點已存在")
			return
		}
		temp = temp.next
	}
	if last {
		temp.next = student
		student.pre = temp
	}else{
		student.next = temp.next
		temp.next = student
		student.next.pre = student
		student.pre = temp
	}

}
//顯示所有節點
func ShowStudentNode(head *Students){
	//設置從頭部開始遍歷
	show := head
	//先判斷是否為空鏈表
	if show.next == nil {
		fmt.Println("鏈表為空")
		return
	}
	for {
		if show.next == nil { 
			fmt.Println("最后節點的前一個節點信息")
			fmt.Printf("學生編號:%v,姓名:%v\n", show.pre.num, show.pre.name)
			return
		}
		fmt.Printf("學生編號:%v,姓名:%v\n", show.next.num, show.next.name)
		show = show.next
	}
}

//刪除節點
func DelStudentNode(head *Students, num int){
	temp := head
	if temp.next == nil {
		fmt.Println("鏈表為空")
		return
	}
	//用於判斷是否為最后一個節點
	last := false
	for {
		if temp.next.num == num {
			//再判斷一下是否為最后一個節點
			if temp.next.next == nil {
				last = true
			}
			break
		}else if temp.next == nil {
			fmt.Println("節點不存在")
			return
		}
		temp = temp.next
	}

	if last {
		temp.next = nil
	}else{
		temp.next = temp.next.next
		temp.next.pre = temp
	}
}

func main() {
	//初始化一個頭結點
	head := &Students{}
	//添加新節點
	student1 := &Students{
		num : 1,
		name : "james",
	}
	student2 := &Students{
		num : 2,
		name : "kobe",
	}
	student5 := &Students{
		num : 5,
		name : "jorden",
	}
	student3 := &Students{
		num : 3,
		name : "shark",
	}
	// 添加節點
	InsertStudentNode1(head, student1)
	InsertStudentNode1(head, student2)
	InsertStudentNode1(head, student5)
	InsertStudentNode2(head, student3)
	//獲取
	ShowStudentNode(head)
	//刪除編號為5的學生
	DelStudentNode(head, 1)
	fmt.Println("刪除后----------------")
	//獲取
	ShowStudentNode(head)
}
結果
[ `go run doubleChainTable.go` | done ]
	學生編號:1,姓名:james
	學生編號:2,姓名:kobe
	學生編號:3,姓名:shark
	學生編號:5,姓名:jorden
	最后節點的前一個節點信息
	學生編號:3,姓名:shark
	刪除后----------------
	學生編號:2,姓名:kobe
	學生編號:3,姓名:shark
	學生編號:5,姓名:jorden
	最后節點的前一個節點信息
	學生編號:3,姓名:shark

 四:環形單向鏈表

①:介紹,參考環形數組隊列

②:環形單向鏈表與單向鏈表和雙向鏈表不同之處在於,head也要存放數據

③:使用舉例

package main

import (
	"fmt"
)

type Students struct{
	num int
	name string
	next *Students
}
//尾部添加
func InsertStudentNode1(head *Students, student *Students){
	temp := head
	//先判斷頭部是否為空
	if temp.next == nil {
		temp.num = student.num
		temp.name = student.name
		//自環
		temp.next = temp
		return
	}
	for {
		if temp.next == head {
			break
		}
		temp = temp.next
	}
	student.next = head
	temp.next=student
}

//顯示所有節點
func ShowStudentNode(head *Students){
	//設置從頭部開始遍歷
	show := head
	//先判斷是否為空鏈表
	if show.next == nil {
		fmt.Println("鏈表為空")
		return
	}
	for {
		fmt.Printf("學生編號:%v,姓名:%v\n", show.num, show.name)
		if show.next == head { 
			break
		}
		show = show.next
	}
}
//刪除節點
func DelStudentNode(head *Students, num int) *Students{
	temp := head
	helper := head//幫助節點跳過將要刪除的節點
	if temp.next == nil {
		fmt.Println("鏈表為空")
		return head
	}
	//判斷是否只有一個節點
	if temp.next == head {
		if temp.num == num {
			temp.next = nil
		}else{
			fmt.Println("節點不存着")
		}
		return head
	}
	//將helper定位到最后一個節點
	for {
		if helper.next == head{
			break
		}
		helper = helper.next
	}
	//當節點有多個時
	flag := true
	for{
		if temp.next == head{
			break
		}
		if temp.num == num {
			if temp == head{//判斷是否刪除頭節點
				head = head.next
			}
			helper.next = temp.next
			fmt.Println("num=",num)
			flag = false
			break
		}
		temp = temp.next
		helper = helper.next
	}
	
	if flag {
		if temp.num == num {
			//說明要刪除的節點是最后一個,這時temp已經指向最后一個節點
			helper.next = temp.next
		}else{
			fmt.Println("節點不存在")
		}
	}
	//防止要刪除的節點是頭部,返回最新的頭部位置
	return head
}
func main() {
		//初始化一個頭結點
	head := &Students{}
	//添加新節點
	student1 := &Students{
		num : 1,
		name : "james",
	}
	student2 := &Students{
		num : 2,
		name : "kobe",
	}
	student3 := &Students{
		num : 3,
		name : "shark",
	}
	student4 := &Students{
		num : 4,
		name : "shark",
	}
	// 添加節點
	InsertStudentNode1(head, student1)
	InsertStudentNode1(head, student2)
	InsertStudentNode1(head, student3)
	InsertStudentNode1(head, student4)
	// 獲取
	ShowStudentNode(head)
	//刪除編號為5的學生
	head = DelStudentNode(head, 1)
	fmt.Println("刪除后----------------")
	//獲取
	ShowStudentNode(head)
}
結果
[ `go run circleChainTable.go` | done ]
	學生編號:1,姓名:james
	學生編號:2,姓名:kobe
	學生編號:3,姓名:shark
	學生編號:4,姓名:shark
	num= 1
	刪除后----------------
	學生編號:2,姓名:kobe
	學生編號:3,姓名:shark
	學生編號:4,姓名:shark

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM