使用Go实现LinkTable库

qq_41606648 2022-04-07 02:28:56

1.定义一个链表及其节点

1.1.定义链表节点:

链表节点(以下称为LinkTableNode,或LTN)定义为具有指向同类型LTN节点的指针域,以及一个记录有int数据的数据域:

//define each node in this linktable which include a pointer to the fellow
//and the data of itself, if needed, data can be any form, not just "int".
type LinkTableNode struct {
	pNext *LinkTableNode
	data  int
}

1.2.定义链表:

链表(以下称为LinkTable,或LT)定义为具有指向LTN节点的头节点指针域,以及一个记录有int型链表长度信息的数据域:

//define the structure of this linktable.
type LinkTable struct {
	pHead  *LinkTableNode
	length int
}

————————————————————stage 1 clear————————————————————

 

2.创建链表:

创建链表思路:创建(new)一个指向LT类型链表的指针,令其指向的链表头节点为空域,长度为0,并返回该*LT指针:

//create one linktable defined above, and return its head-pointer.
func CreateLinkTable() *LinkTable {
	var pLinkTable *LinkTable = new(LinkTable)

	if pLinkTable == nil {
		return nil
	}

	//one linktable is in null head-pointer and 0 length when initially made.
	pLinkTable.pHead = nil
	pLinkTable.length = 0

	return pLinkTable
}

————————————————————stage 2 clear————————————————————

 

3.删除链表:

删除链表思路:若链表本身为空链表,无需额外操作,但仍返回一个值以为更多判断(本案例中并没有);不为空链表时,逐个删除节点,直至链表表头为空:

//delete one structured linktable, and return whether this operation
//complete(1) or fail(0)
func DeleteLinkTable(pLinkTable *LinkTable) int {
	if pLinkTable == nil {
		return 0
	}

	//delete each node in this linktable
	for pLinkTable.pHead != nil {
		pLinkTable.pHead = pLinkTable.pHead.pNext
	}

	//finally, put its length to 0
	pLinkTable.length = 0

	return 1
}

————————————————————stage 3 clear————————————————————

 

4.增加节点:

增加节点的方式有很多,因其目的不同而各不相同,本案例中选用“在已知链表的指定位置(从0开始计下标)插入给定节点”的理解方式。

首先对链表是否合法、给定节点是否为空以及节点插入位置进行判断,接着判断若插入0号位置的特殊情况(细分链表是否为空链表),最后实现对一般位置的插入:找到插入位置的上一个节点,令该节点指向给定节点,再指向该节点的原本下一节点:

//put a new node "pNode" into the very "position" of the linktable "pLinkTable"
func AddLinkTableNode(pLinkTable *LinkTable, pNode *LinkTableNode, position int) int {
	if pLinkTable == nil || pNode == nil {
		return 0
	}

	//if position needed is far beyond the linktable can bear, regard it as a failure
	if position > pLinkTable.length {
		fmt.Printf("out of range\n")
		return -1
	}

	//find its position and insert it in
	if position == 0 {
		if pLinkTable.length != 0 {
			pNode.pNext = pLinkTable.pHead.pNext
		}
		pLinkTable.pHead = pNode
	} else {
		var tmpNodepointer *LinkTableNode = pLinkTable.pHead
		for position != 1 {
			tmpNodepointer = tmpNodepointer.pNext
			position -= 1
		}
		pNode.pNext = tmpNodepointer.pNext
		tmpNodepointer.pNext = pNode
	}
	pLinkTable.length += 1

	return 1
}

————————————————————stage 4 clear————————————————————

 

5.删除节点:

同4理,删除节点采取的理解方式为“删除已知链表的指定位置(从0开始计下标)对应的节点”。

首先对链表是否合法、给定节点是否为空以及节点插入位置进行判断,接着判断若插入0号位置的特殊情况,最后一般情况使用".pnext.pnext" 替代".pnext"的常见方法:

//delete the node in the very "position" in the linktable "pLinkTable"
func DelLinkTableNode(pLinkTable *LinkTable, position int) int {
	if pLinkTable == nil && pLinkTable.pHead == nil {
		return 0
	}
	//if position needed is far beyond the linktable can bear, regard it as a failure
	if (position + 1) > pLinkTable.length {
		fmt.Printf("out of range\n")
		return -1
	}

	//find it and make ".pnext.pnext" instead of ".pnext"
	if position == 0 {
		pLinkTable.pHead = pLinkTable.pHead.pNext
	} else {
		var tmpNodepointer *LinkTableNode = pLinkTable.pHead
		for position != 1 {
			tmpNodepointer = tmpNodepointer.pNext
			position -= 1
		}
		tmpNodepointer.pNext = tmpNodepointer.pNext.pNext
	}
	pLinkTable.length -= 1

	return 1
}

————————————————————stage 5 clear————————————————————

 

6.查找节点:

“查找指定目标数是否存在于已知链表中,如果存在,返回其首次出现的下标(从0开始计),否则返回-1”。

遍历链表,若存在节点的数据域与目标值相同,返回该下标,无论是链表为空还是链表中确实没有,找不到则返回-1:

//if target is in this linktable, print its position(start from 0), if not, warn it
func FindLinkTableNode(pLinkTable *LinkTable, target int) int {
	if pLinkTable.pHead == nil {
		fmt.Print("Null LinkTable, nothing could be found\n")
		return -1
	}
	var position int = 0
	var tmpNodepointer *LinkTableNode = pLinkTable.pHead
	for position < pLinkTable.length {
		if tmpNodepointer.data == target {
			fmt.Print("Found it\n")
			return position
		}
		tmpNodepointer = tmpNodepointer.pNext
		position += 1
	}
	fmt.Print("Not founded\n")
	return -1
}

————————————————————stage 6 clear————————————————————

 

7.输出链表:

遍历并输出值,直至指向空节点:

//print val in each node
func PrintLinkTable(pLinkTable *LinkTable) {
	if pLinkTable != nil {
		var tmpNodepointer *LinkTableNode = pLinkTable.pHead
		for tmpNodepointer != nil {
			fmt.Printf("%d ", tmpNodepointer.data)
			tmpNodepointer = tmpNodepointer.pNext
		}
		fmt.Printf("\n")
	}
}

————————————————————stage 7 clear————————————————————

 

8.主程序与测试:

主程序中使用乱序输入、随机指定数字进行查找、删除节点乃至整个链表进行验证,结果均符合预期:

//here 's the main, including the test
func main() {
	pLinkTable := CreateLinkTable()

	val0 := &LinkTableNode{nil, 0}
	val1 := &LinkTableNode{nil, 1}
	val2 := &LinkTableNode{nil, 2}
	val3 := &LinkTableNode{nil, 3}
	val4 := &LinkTableNode{nil, 4}

	//as expected, the result should be:
	//0 1 2 3 4
	AddLinkTableNode(pLinkTable, val0, 0)
	AddLinkTableNode(pLinkTable, val2, 1)
	AddLinkTableNode(pLinkTable, val4, 2)
	AddLinkTableNode(pLinkTable, val1, 1)
	AddLinkTableNode(pLinkTable, val3, 3)
	PrintLinkTable(pLinkTable)

	//as expected, the result should be:
	//Fount it
	//Not founded
	FindLinkTableNode(pLinkTable, 3)
	FindLinkTableNode(pLinkTable, 5)

	//as expected, the result should be:
	//0 2 3 4
	DelLinkTableNode(pLinkTable, 1)
	PrintLinkTable(pLinkTable)

	DeleteLinkTable(pLinkTable)
	PrintLinkTable(pLinkTable)
}

 ————————————————————stage 8 clear————————————————————

————————————————————all stages clear————————————————————

 

作者代码:384

...全文
201 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

571

社区成员

发帖
与我相关
我的任务
社区描述
软件工程教学新范式,强化专项技能训练+基于项目的学习PBL。Git仓库:https://gitee.com/mengning997/se
软件工程 高校
社区管理员
  • 码农孟宁
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧