Go数据结构之链表

Posted louis181214

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 ", 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
", show.pre.num, show.pre.name)
			return
		}
		fmt.Printf("学生编号:%v,姓名:%v
", 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
", 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

 

























































































































以上是关于Go数据结构之链表的主要内容,如果未能解决你的问题,请参考以下文章

linux内核数据结构之链表

Java数据结构线性表之链表

Java数据结构线性表之链表

Java数据结构线性表之链表

JavaScript数据结构之链表

JavaScript数据结构之链表