链表定义、尾部插入节点、头部插入节点、查找链表的第n个几点、查找链表的倒数第n个节点(3种方法)

链表定义

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
	}
}
posted @ 2022-05-07 15:15  专职  阅读(129)  评论(0编辑  收藏  举报