golang 双链表插入,删除,读取

链表

  1. 链表分类,单链表,双链表,环链表

  2. 时间复杂度,修改时间复杂度O(1)

  3. 查询时间复杂度,O(n)

    package main
    
    import "fmt"
    
    type Node struct {
    	Data int
    	Next *Node
    	Pre  *Node
    }
    
    type LinkedList struct {
    	head    *Node
    	current *Node
    	tail    *Node
    }
    
    func CreateLinkedList(data []int) {
    	link := LinkedList{}
    	var currentNode *Node
    	for i := 0; i < len(data); i++ {
    		currentNode = new(Node)
    		currentNode.Data = data[i]
    		insertNode(&link, currentNode)
    	}
    	ShowLinkedList(link)
    }
    
    /**
    插入
    */
    func insertNode(list *LinkedList, node *Node) {
    	if list.head == nil {
    		//头指针,当前指针,尾指针都指向当前节点
    		list.head = node
    		list.current = node
    		list.tail = node
    	} else {
    		//把节点串到最后一个节点的下一个节点
    		list.tail.Next = node
    		//把当前节点的前向指针指向上一个节点
    		node.Pre = list.tail
    		//尾指针指向新节点
    		list.tail = node
    	}
    }
    
    /**
    展示每个节点数据
    */
    func ShowLinkedList(link LinkedList) {
    	var currentNode *Node
    	for currentNode = link.head; currentNode != nil; {
    		fmt.Printf("Node:%d\n", currentNode.Data)
    		currentNode = currentNode.Next
    	}
    }
    
    func main() {
    	data := []int{1, 21, 31, 41, 51, 61, 2, 3, 4, 5, 6, 8, 3, 9}
    	CreateLinkedList(data)
    }
    
    
### Golang 常见面试题及基础知识整理 #### 1. Go 的测试哲学 Go 的测试哲学强调简单性和集成性。通过标准库中的基本工具以及语言设计模式,开发者能够轻松编写和维护单元测试。对于更复杂的情景,如模拟(mocking),可以通过第三方库获得支持[^1]。 #### 2. 性能测试与基准测试 (Benchmark) 在 Go 中,性能测试通常涉及测量代码执行时间、内存分配情况以及其他资源消耗指标。基准测试是一种专门用于评估代码性能的技术。它允许开发人员定义一组特定条件下的重复操作,并记录其耗时。例如: ```go package main import "testing" func BenchmarkExample(b *testing.B) { for i := 0; i < b.N; i++ { // 被测逻辑 } } ``` 此代码片段展示了如何创建一个简单的基准测试函数 `BenchmarkExample`,其中循环次数由框架自动调整以确保足够的采样量[^1]。 #### 3. 并发安全性 - Map 在多 Goroutine 下的行为 当多个 goroutines 同时访问共享的 map 数据结构时需要注意同步控制。如果仅存在并发读取,则不会引发任何问题;然而一旦有写入发生便可能引起竞态条件(data race),进而造成程序异常终止(panic)。为了防止这种情况的发生,在每次修改之前都会设置一个写标记位(writer flag),而在完成相应动作后再将其清除[^2]。 #### 4. 使用 List 实现有序 Map 有时我们需要保持键值对插入顺序的同时还能快速检索它们。一种解决方案就是利用内置容器类型 `list.List` 来辅助管理这些条目。具体做法如下所示: - 创建双向链表实例; - 将新元素既存放到哈希映射(map)里也追加到列表尾端; - 当迭代整个集合时只需顺着节点逐一访问即可得到原始排列次序。 这种方法虽然牺牲了一定程度上的空间效率但却换取了更好的可预测行为特性[^3]。 #### 5. Type Switches & Interface Assertions Type switches 是另一种形式的选择语句,它可以用来判断某个接口变量实际存储的是哪种具体类型的对象。下面给出两个版本对比说明为什么第一个例子会报错而第二个却正常工作的原因在于前者试图直接作用于非 interface 类型之上违反语法规定所致[^4]: 错误示范: ```go // 错误用法 switch key.(type){ case int: ... default :... } ``` 正确示范: ```go func identify(key interface{}) string{ switch t:=key.(type){ case int:return fmt.Sprintf("%v is an integer",t) case float64:return fmt.Sprintf("%v is a floating point number",t) default:return "Unknown type" } } fmt.Println(identify(42)) // Output: 42 is an integer fmt.Println(identify(math.Pi)) // Output: 3.141592...is a floating point number ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小哥(xpc)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值