Golang(五十一)[线性存储-链表-环形链表]

是单向链表的特例。将单向链表的尾结点,指向第一个数据结点(而不是指向头结点)

1.初始化

mkdir -p linkList
cd linkList
go mod init linkList
touch linkList.go
vim linkList.go

2.定义环形链表结点结构体

// 定义环形链表的结点结构体
type LinkNode struct {
	// 定义环形链表的数据域
	Data interface{}
	// 定义环形链表指针域
	Next *LinkNode
}

3.创建环形链表

// 创建环形链表
func (node *LinkNode) NewLinkList(data ...interface{}) {
	// 容错处理
	if node == nil || len(data) == 0 {
		return
	}
	// 保存head结点
	head := node
	// 遍历data数据创建新结点
	for _, v := range data {
		// 创建新结点,并初始化
		newNode := new(LinkNode)
		newNode.Data = v
		newNode.Next = nil

		// 将当前结点的指针域指向新结点
		node.Next = newNode
		// 更新当前结点
		node = node.Next
	} // 遍历结束,node在尾结点
	// 将尾结点的指针域指向第一个数据结点(head.Next)
	node.Next = head.Next
	// 将head结点赋值给node,以便node回到head结点位置
	node = head
}

4.打印双向链表

1.递归实现

// 正向打印环形链表--递归实现
var start interface{}

func (node *LinkNode) Print1() {
	// 容错处理
	if node == nil {
		return
	}
	// 如果是头结点就给第一个数据结点标记赋值[头结点的数据域为nil]
	if node.Data == nil {
		// 做第一个数据结点的标记
		start = node.Next
	}
	// 数据结点的特点:有数据数据域
	if node.Data != nil {
		fmt.Print(node.Data, " ")
		//  递归的出口: 此时应该在尾结点[数据域不为空,],其下一个结点(node.Next)即将回到第一个数据结点
		if node.Next == start {
			// 在递归调用出口处打印换行
			fmt.Println()
			return
		}
	}
	// 递归实现
	node.Next.Print1()
}

测试

func main() {
	list := new(LinkNode)
	list.NewLinkList(1, 2, 3, 4, 5, 6, 7)
	list.Print1()
}

1.循环实现

// 正向打印环形链表--循环实现
func (node *LinkNode) Print2() {
	// 容错处理
	if node == nil {
		return
	}
	// 定义第一个数据结点的位置标记
	start := node.Next
	for node.Next != nil {
		node = node.Next // 更新node结点位置,在初始时,可以跳过head指针[head结点:没有数据域(nil),只有指针域(指向第一个数据结点)]
		// 数据结点的特点:有数据数据域
		if node.Data != nil {
			fmt.Print(node.Data, " ")
		}
		// 判断是否在尾结点(即node.Next是否指向第一个数据结点位置)
		if start == node.Next {
			// 已经在尾结点,直接返回
			return
		}
	}
	// 打印换行
	fmt.Println()
}

测试

func main() {
	list := new(LinkNode)
	list.NewLinkList(1, 2, 3, 4, 5, 6, 7)
	list.Print2()
}

5.获取双向链表的长度[数据结点长度]

// 获取数据结点长度
func (node *LinkNode) Length() (length int) {
	// 容错处理
	if node == nil {
		return
	}
	// 标记第一个数据结点的位置:head结点的下一个结点[node.Next]
	start := node.Next
	for {
		node = node.Next // 初始可以跳过head结点
		length++
		// 如果当前在尾结点,即指针域指向第一个数据结点时
		if start == node.Next {
			break
		}
	}
	/* // 也可以使用如下方法获取:
	for {
		node = node.Next // 初始跳过head 结点
		if node.Data != nil {
			length++
		}
		// 如果当前在尾结点,即指针域指向第一个数据结点时
		if start == node.Next {
			break
		}
	} */
	return
}

测试

func main() {
	list := new(LinkNode)
	list.NewLinkList(1, 2, 3, 4, 5, 6, 7)
	list.Print1()
	length := list.Length()
	fmt.Println("环形链表的数据结点长度为:", length)
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章