golang--算法--链表

需要掌握的5个常见的链表操作:

  • 单链表反转;
  • 链表中的环检测;
  • 两个有序链表的合并;
  • 删除链表倒数第n个结点;
  • 求链表的中间结点;

实现代码如下:

package main

import "fmt"

type Node struct {
	data int
	next *Node
}

type HeadNode struct {
	num int
	first *Node
}

//打印
func printNode(head *HeadNode) {
	if head.first == nil {
		 fmt.Printf("node is null\n")
	} else {
		curNode := head.first

		for curNode != nil {
			fmt.Printf("data is: %v\n", curNode)
			curNode = curNode.next
		}
	}
}

//插入
func insertNode(head *HeadNode, node *Node){
	if head.first ==nil {
		head.num = 1
		head.first = node
	} else {
		curNode := head.first

		for curNode.next != nil {
			 curNode = curNode.next
		}

		curNode.next = node
		head.num++
	}
}

// 1.单链表反转
func invertList(head *HeadNode) {
	if head.first == nil {
		return
	}

	if head.first.next == nil {
		return
	}

	preNode := head.first
	curNode := head.first.next

	preNode.next = nil

	for curNode.next != nil {
		nextNode := curNode.next

		curNode.next = preNode

		preNode = curNode
		curNode = nextNode
	}

	curNode.next = preNode
	head.first = curNode
}

// 2.链表中有环检测
func checkListCycle(head *HeadNode) bool {
	if head.first == nil {
		return false
	}
	slowNode := head.first
	fastNode := head.first

	for fastNode.next.next != nil{
		slowNode = slowNode.next
		fastNode = fastNode.next.next
		if slowNode == fastNode{
			return true
		}
	}

	return false
}

// 3.两个有序链表的合并
func meregeList(headFirst, headSecond *HeadNode) *HeadNode{
	newHead := &HeadNode{0, nil}
	firstListNode := headFirst.first
	secondListNode := headSecond.first

	for firstListNode != nil && secondListNode != nil{
		 if firstListNode.data < secondListNode.data {
		 	tmpNode := &Node{firstListNode.data, nil}
		 	insertNode(newHead, tmpNode)
		 	firstListNode = firstListNode.next
		 } else {
			 tmpNode := &Node{secondListNode.data, nil}
			 insertNode(newHead, tmpNode)
			 secondListNode = secondListNode.next
		 }
	}

	for firstListNode != nil{
		tmpNode := &Node{firstListNode.data, nil}
		insertNode(newHead, tmpNode)
		firstListNode = firstListNode.next
	}

	for secondListNode != nil{
		tmpNode := &Node{secondListNode.data, nil}
		insertNode(newHead, tmpNode)
		secondListNode = secondListNode.next
	}

	return newHead
}

// 4.删除链表倒数第n个结点
func deleteNodeByNum(head *HeadNode, num int){
	firstNode := head.first
	secondNode := head.first

	//两个node之前差值为num
	for i:=1; i<=num+1; i++{
		firstNode = firstNode.next
	}

	for firstNode != nil {
		firstNode = firstNode.next
		secondNode = secondNode.next
	}

	secondNode.next = secondNode.next.next
}

// 5.求链表的中间结点
func selectMiddleNode(head *HeadNode) *Node{
	if head.first == nil {
		return nil
	}
	slowNode := head.first
	fastNode := head.first

	for fastNode != nil && fastNode.next != nil {
		slowNode = slowNode.next
		fastNode = fastNode.next.next
	}

	return slowNode
}

func main(){
	head := &HeadNode{0, nil}

	insertNode(head, &Node{1, nil})
	insertNode(head, &Node{3, nil})
	insertNode(head, &Node{5, nil})
	insertNode(head, &Node{7, nil})
	printNode(head)
	
	fmt.Printf("all node num is: %v\n", head.num)

	//1.反转链表
	//invertList(head)
	//printNode(head)

	//head.first.next.next.next = head.first.next
	//2.检测是否存在环
	flag := checkListCycle(head)
	fmt.Printf("list is have cycle flag is: %v\n\n", flag)


	head2 := &HeadNode{0, nil}

	insertNode(head2, &Node{2, nil})
	insertNode(head2, &Node{4, nil})
	insertNode(head2, &Node{6, nil})
	insertNode(head2, &Node{8, nil})
	printNode(head2)

	fmt.Printf("after merege is\n\n")

	//3.合并两个有序链表
	newHead := meregeList(head, head2)
	printNode(newHead)


	fmt.Printf("after delete node by num desc is\n\n")
	// 4.删除链表倒数第n个结点
	deleteNodeByNum(newHead, 3)
	printNode(newHead)

	// 5.求链表的中间结点
	midNode := selectMiddleNode(newHead)
	fmt.Printf("mid node is: %v\n", midNode)

	
}

优质博文参考链接:https://www.cnblogs.com/huangliang-hb/p/10855558.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值