《大话数据结构》学习笔记 —— 03 线性表之单链表(golang实现)


单链表


定义

如果链表中的每个结点只包含一个指针,则该链表称为单链表

单链表结构如图所示:

《大话数据结构》学习笔记 —— 03 线性表之单链表(golang实现)_第1张图片



代码实现

package SingleLinkling

import (
	"fmt"
)

// 定义单链表接口
type SingleLink interface {

	// 返回第一个数据结点
	GetFirstNode() *SingleLinkNode

	// 插入结点(头插法)
	InsertNodeFront(node *SingleLinkNode)

	// 插入结点(尾插法)
	InsertNodeBack(node *SingleLinkNode)

	// 插入某结点前
	InsertNodeValueFront(dest interface{}, node *SingleLinkNode) bool

	// 插入某结点后
	InsertNodeValueBack(dest interface{}, node *SingleLinkNode) bool

	// 获取指定索引上的结点
	GetNodeAtIndex(index int) *SingleLinkNode

	// 删除结点
	DeleteNode(dest *SingleLinkNode) bool

	// 删除指定索引上的结点
	DeleteAtIndex(index int) bool

	// 返回字符串
	String() string
}

// 单链表
type SingleLinkList struct {
	// 头指针
	head *SingleLinkNode
	// 长度
	length int
}

// 初始化单链表
func NewSingleLinkList() *SingleLinkList {

	// 初始化头结点
	head := NewSingleLinkNode(nil)

	return &SingleLinkList{
		head:   head,
		length: 0,
	}
}

// 获取第一个数据结点
func (list *SingleLinkList) GetFirstNode() *SingleLinkNode {
	return list.head.pNext
}

// 获取指定索引上的结点
func (list *SingleLinkList) GetNodeAtIndex(index int) *SingleLinkNode {

	// 索引越界
	if index > list.length-1 || index < 0 {
		return nil
	}

	// 备份头结点
	bak := list.head

	// 向后循环
	for index > -1 {
		bak = bak.pNext
		index--
	}

	return bak
}

// 头部插入
func (list *SingleLinkList) InsertNodeFront(node *SingleLinkNode) {

	// 空链表
	if list.head == nil {

		// 第一个数据结点设为新结点
		list.head.pNext = node

		// 新结点指针指向nil
		node.pNext = nil

		list.length++
		return
	}

	// 备份头结点
	bak := list.head

	// 新结点的指针,指向原来的第一个数据结点
	node.pNext = bak.pNext

	// 头结点指向新结点
	bak.pNext = node

	list.length++
	return
}

// 尾部插入
func (list *SingleLinkList) InsertNodeBack(node *SingleLinkNode) {

	// 空链表
	if list.head == nil {

		// 第一个数据结点设为新结点
		list.head.pNext = node

		// 新结点指针指向nil
		node.pNext = nil

		list.length++
		return
	}

	// 备份头结点
	bak := list.head

	// 循环到链表末尾
	for bak.pNext != nil {
		bak = bak.pNext
	}

	// 终端结点的指针指向新结点
	bak.pNext = node

	list.length++
	return
}

// 插入某结点前
func (list *SingleLinkList) InsertNodeValueFront(dest interface{}, node *SingleLinkNode) bool {

	// 备份头结点
	bak := list.head

	// 循环到末尾,直至找到目标结点
	for bak.pNext != nil && bak.pNext.value != dest {
		bak = bak.pNext
	}

	// 找到
	if bak.pNext.value == dest {

		// 目标结点的上一个数据结点的指针,赋值给新结点的指针
		node.pNext = bak.pNext

		// 目标结点的上一个数据结点的指针,指向新结点
		bak.pNext = node

		list.length++
		return true
	}

	return false

}

// 插入某结点后
func (list *SingleLinkList) InsertNodeValueBack(dest interface{}, node *SingleLinkNode) bool {

	// 备份头结点
	bak := list.head

	// 循环到末尾,直至找到目标结点
	for bak.pNext != nil && bak.pNext.value != dest {
		bak = bak.pNext
	}

	// 找到
	if bak.pNext.value == dest {

		// 目标结点的指针赋值给新结点的指针
		node.pNext = bak.pNext.pNext

		// 目标结点的指针指向新结点
		bak.pNext.pNext = node

		list.length++
		return true
	}

	return false

}

// 删除结点
func (list *SingleLinkList) DeleteNode(dest *SingleLinkNode) bool {

	// 备份头结点
	bak := list.head

	// 循环到末尾,直至找到目标结点
	for bak.pNext != nil && bak.pNext != dest {
		bak = bak.pNext
	}

	// 找到
	if bak.pNext == dest {

		// 目前结点的指针赋值给目标结点的上一个数据结点的指针
		bak.pNext = bak.pNext.pNext

		list.length--
		return true
	}

	return false
}

// 删除指定索引上的结点
func (list *SingleLinkList) DeleteAtIndex(index int) bool {

	// 索引越界
	if index > list.length-1 || index < 0 {
		return false
	}

	// 备份头结点
	bak := list.head

	// 向后循环,找到前一个结点
	for index > 0 {
		bak = bak.pNext
		index--
	}

	// 目前结点的指针赋值给目标结点的上一个数据结点的指针
	bak.pNext = bak.pNext.pNext
	list.length--

	return true
}

// 获取链表中间结点
func (list *SingleLinkList) GetMid() *SingleLinkNode {

	// 链表只有一个结点
	if list.head.pNext == nil {
		return nil
	}

	phead1 := list.head
	phead2 := list.head

	for phead2 != nil && phead2.pNext != nil {
		phead1 = phead1.pNext
		phead2 = phead2.pNext.pNext
	}

	return phead1
}

// 链表反转
func (list *SingleLinkList) ReverseList() {

	// 链表为空或者只有一个结点
	if list.head == nil || list.head.pNext == nil {
		return
	}

	// 前一个结点
	var pre *SingleLinkNode

	// 当前结点
	cur := list.head.pNext

	for cur != nil {
		pre, cur, cur.pNext = cur, cur.pNext, pre
	}

	list.head.pNext = pre

}

// 返回字符串
func (list *SingleLinkList) String() string {

	var listString string

	// 头结点
	p := list.head

	// 循环输出
	for p.pNext != nil {
		listString += fmt.Sprintf("%v-->", p.pNext.value)
		p = p.pNext
	}

	listString += fmt.Sprintf("nil")

	return listString
}



时间复杂度

单链表,在读数据时,时间复杂度为O(n);

而在进行插入、删除操作时,时间复杂度为O(1)。

你可能感兴趣的:(数据结构)