链表定义
package main
import "fmt"
// Student 每个节点包含下一个节点的地址,这样把所有的节点都串起来了,通常把链表中的第一个节点叫做链表头
/*
type Student struct {
Name string
Next *Student
}
*/
// 定义一个简单的链表
type Student struct {
Name string
Age uint8
Score float32
Next *Student
}
func main() {
// 定义一个头节点
var head Student
head.Name = "zhang"
head.Age = 18
head.Score = 88.5
var stu1 Student
stu1.Name = "li"
stu1.Age = 35
stu1.Score = 60
// 将两个节点连接起来
head.Next = &stu1
var p *Student = &head // 将p指向链表的头部
for p != nil {
fmt.Println(*p)
p = p.Next
}
}
尾部插入节点
package main
import (
"fmt"
"math/rand"
)
// 每个节点都包含下一个节点的地址,这样就把所有的节点都串起来了,通常我们把第一个节点叫做链表头
// Student 定义一个链表结构
type Student struct {
Name string
Age int
Score float32
Next *Student
}
func trans(node *Student) {
for node != nil {
fmt.Println(*node)
node = node.Next
}
}
func main() {
// 通常我们把第一个节点叫做链表头
var head Student
head.Name = "zhang"
head.Age = 18
head.Score = 88.5
// 尾部插入法
var tail *Student = &head // 因为是指针类型,所以可以修改它的Next值
for i := 0; i < 10; i++{
var stu = Student{
Name: fmt.Sprintf("stu%d", i),
Age: rand.Intn(100),
Score: rand.Float32() * 100,
}
tail.Next = &stu // 把尾部节点的下一个节点设置为新生成的节点
tail = &stu // 把新生成的节点赋值给尾部节点
}
// 输出所有节点
trans(&head)
}
/* 输出结果
{zhang 18 88.5 0xc0000764b0}
{stu0 81 94.05091 0xc0000764e0}
{stu1 47 43.77142 0xc000076510}
{stu2 81 68.682304 0xc000076540}
{stu3 25 15.651925 0xc000076570}
{stu4 56 30.091187 0xc0000765a0}
{stu5 94 81.36399 0xc0000765d0}
{stu6 62 38.06572 0xc000076600}
{stu7 28 46.888985 0xc000076630}
{stu8 11 29.310184 0xc000076660}
{stu9 37 21.855305 <nil>}
*/
头部插入节点
package main
import (
"fmt"
"math"
"math/rand"
)
// 每个节点都包含下一个节点的地址,这样所有的节点都串起来了,通常我们把第一个节点叫做链表头
type Student struct {
Name string
Age int
Score float64
Next *Student
}
func trans(s *Student){
for s != nil {
fmt.Println(*s)
s = s.Next
}
}
func main() {
var head *Student = new(Student)
head.Name = "zhang"
head.Age = 18
head.Score = 88.5
// 头部插入法
for i := 0; i < 10; i++{
var stu = Student{
Name: fmt.Sprintf("stu%d", i + 1),
Age: rand.Intn(100),
Score: math.Round(rand.Float64() * 100),
}
stu.Next = head
head = &stu
}
trans(head)
}
/*
{stu10 37 22 0xc000076660}
{stu9 11 29 0xc000076630}
{stu8 28 47 0xc000076600}
{stu7 62 38 0xc0000765d0}
{stu6 94 81 0xc0000765a0}
{stu5 56 30 0xc000076570}
{stu4 25 16 0xc000076540}
{stu3 81 69 0xc000076510}
{stu2 47 44 0xc0000764e0}
{stu1 81 94 0xc0000764b0}
{zhang 18 88.5 <nil>}
*/
查找链表的第n个节点,例如查找第5个节点
package main
import (
"fmt"
"math/rand"
)
// 每一个节点都包含下一个节点的地址,所有的节点都被串起来,通常我们把第一个节点称为链表头
type Student struct {
Name string
Age int
Score float32
Next *Student
}
func main() {
var head = new(Student)
head.Name = "zhangsan"
head.Age = 18
head.Score = 88.5
var tail *Student = head
for i := 0; i < 10; i++{
var stu = Student{
Name: fmt.Sprintf("stu%d", i),
Age: rand.Intn(100),
Score: rand.Float32() * 100,
}
tail.Next = &stu
tail = &stu
}
// 打印生成的所有节点
//trans(head)
// 查找第n个节点
for i := 1; i <= 5;i++{
if i == 5 {
fmt.Println(*head)
}
head = head.Next
}
}
func trans(s *Student){
for s != nil {
fmt.Println(*s)
s = s.Next
}
}
查找链表的倒数第n个节点
- 方法1,遍历两次,第一次遍历计算链表的长度,然后根据公式num := length-n+1,计算出正序的位置,然后第二次遍历获取num个节点(也就是倒数第n个节点)
package main
import (
"fmt"
"math/rand"
)
// 每一个节点都包含下一个节点的地址,所有的节点都被串起来,通常我们把第一个节点称为链表头
type Student struct {
Name string
Age int
Score float32
Next *Student
}
func main() {
var head = new(Student)
head.Name = "zhangsan"
head.Age = 18
head.Score = 88.5
var tail *Student = head
for i := 0; i < 10; i++{
var stu = Student{
Name: fmt.Sprintf("stu%d", i),
Age: rand.Intn(100),
Score: rand.Float32() * 100,
}
tail.Next = &stu
tail = &stu
}
// 打印生成的所有节点
//trans(head)
// 查找倒数第n个节点, 例如查找倒数第3个节点
// 1. 遍历统计链表长度
var length int
var new_head = head
for new_head != nil {
length++
new_head = new_head.Next
}
// 2. 计算倒数第3个元素是正数第几个元素
num := length - 3 + 1
// 3. 查找链表的正数第num个元素(也就是倒数第3个元素)
for i := 1; i <= num; i++{
if i == num{
fmt.Println(*head)
}
head = head.Next
}
}
func trans(s *Student){
for s != nil {
fmt.Println(*s)
s = s.Next
}
}
- 方法2,构建一个长度为n的channel,遍历将链表的所有节点一次写入channel,先判断channel是已满,满了的话就取出一个,然后继续遍历往队列里面加入
知道把所有的链表节点都遍历完,最后队列中的队尾存放的就是倒数第n个节点,直接取出即可
package main
import (
"fmt"
"math/rand"
)
// 每一个节点都包含下一个节点的地址,所有的节点都被串起来,通常我们把第一个节点称为链表头
type Student struct {
Name string
Age int
Score float32
Next *Student
}
func main() {
var head = new(Student)
head.Name = "zhangsan"
head.Age = 18
head.Score = 88.5
var tail *Student = head
for i := 0; i < 10; i++{
var stu = Student{
Name: fmt.Sprintf("stu%d", i),
Age: rand.Intn(100),
Score: rand.Float32() * 100,
}
tail.Next = &stu
tail = &stu
}
// 打印生成的所有节点
//trans(head)
// 查找倒数第n个节点, 例如查找倒数第3个节点
// 新建一个队列,容量为3
ch := make(chan *Student, 3)
for head != nil {
if len(ch) == 3 {
<-ch
}
ch <- head
head = head.Next
}
fmt.Println(*<-ch)
}
func trans(s *Student){
for s != nil {
fmt.Println(*s)
s = s.Next
}
}
- 方法3,定义两个指针,第一个指针指向头节点,第二个指针指向正数第n个节点,然后进行遍历,每遍历一次,两个指针都向后移动一个节点
当第二个指针的Next为nil时,退出循环,此时的第一个指针就是我们要找的倒数第n个节点
package main
import (
"fmt"
"math/rand"
)
// 每一个节点都包含下一个节点的地址,所有的节点都被串起来,通常我们把第一个节点称为链表头
type Student struct {
Name string
Age int
Score float32
Next *Student
}
func main() {
var head = new(Student)
head.Name = "zhangsan"
head.Age = 18
head.Score = 88.5
var tail *Student = head
for i := 0; i < 10; i++{
var stu = Student{
Name: fmt.Sprintf("stu%d", i),
Age: rand.Intn(100),
Score: rand.Float32() * 100,
}
tail.Next = &stu
tail = &stu
}
// 打印生成的所有节点
//trans(head)
// 查找倒数第n个节点, 例如查找倒数第3个节点
var start, end = head, head
var n = 3
for i := 0; i < n - 1; i++{
end = end.Next
}
for end.Next != nil {
start = start.Next
end = end.Next
}
fmt.Println(*start)
}
func trans(s *Student){
for s != nil {
fmt.Println(*s)
s = s.Next
}
}