zoukankan      html  css  js  c++  java
  • 单链表及双向链表的代码实现golang Marathon

    单链表

    package linkedList
    
    // 单链表的实现
    type ListNode struct {
    	Val int
    	Next *ListNode
    }
    
    type MyLinkedList struct {
    	size int
    	head *ListNode
    }
    
    /*
    // initialize struct
    func Constructor() MyLinkedList  {
    	return MyLinkedList{0, &ListNode{}}
    }
     */
    
    func (this *MyLinkedList) Get(index int) int {
    	// 通过索引获取链表节点的值
    	if index < 0 || index >= this.size {
    		return -1
    	}
    
    	// 通过前继节点获取
    	prev := this.head
    	for i:=0;i<index;i++ {
    		prev = prev.Next
    	}
    	return prev.Next.Val
    }
    
    func (this *MyLinkedList) AddAtIndex(index int, val int)  {
    	// 通过索引插入节点, 先遍历找到前继节点
    	if index < 0 || index > this.size {
    		return
    	}
    	// 找到前继节点
    	prev := this.head
    	for i:=0;i<index;i++ {
    		prev = prev.Next
    	}
    	// 根据给定val生成新节点
    	node := &ListNode{Val: val}
    	// 防止丢失节点,显然新节点指向prev的下个节点
    	node.Next = prev.Next
    	// prev指向新节点
    	prev.Next = node
    
    	// 更新size
    	this.size++
    }
    
    func (this *MyLinkedList) AddAtHead(val int)  {
    	// 头部插入新节点
    	this.AddAtIndex(0, val)
    }
    
    func (this *MyLinkedList) AddAtTail(val int)  {
    	// 尾部插入新节点
    	this.AddAtIndex(this.size, val)
    }
    
    func (this *MyLinkedList) DeleteAtIndex(index int)  {
    	// 通过索引删除节点, 依然通过前继节点操作,直接指向下下个节点即可
    	if index < 0 || index >= this.size {
    		return
    	}
    	// 遍历找到前继节点
    	prev := this.head
    	for i:=0;i<index;i++ {
    		prev = prev.Next
    	}
    	// 前继指向下下个节点
    	prev.Next = prev.Next.Next
    
    	// 更新size
    	this.size--
    }
    

    双向链表

    //+build ignore
    package main
    
    import "fmt"
    
    func main()  {
    	head := ConstrutorD()
    	head.AddAtHead(2)
    	head.AddAtHead(5)
    	head.AddAtHead(7)
    	head.AddAtIndex(3,4)
    	head.AddAtTail(100)
    	head.DeleteAtIndex(3)
    	fmt.Println(head.Get(0))
    	fmt.Println(head.Get(1))
    	fmt.Println(head.Get(2))
    	fmt.Println(head.Get(3))
    }
    
    // 双向链表的实现
    type Node struct {
    	Val int
    	Prev, Next *Node
    }
    
    type MyLinkedListD struct {
    	size int
    	head, tail *Node
    }
    
    // initialize struct
    func ConstrutorD() MyLinkedListD {
    	return MyLinkedListD{}
    }
    
    func (this *MyLinkedListD) Get(index int) int {
    	// 双向链表,根据索引获取值
    	if this.size == 0 || index < 0 || index >= this.size {
    		return -1
    	}
    	// 处理头尾节点,fast-way
    	if index == 0 {
    		return this.head.Val
    	}
    	if index == this.size - 1 {
    		return this.tail.Val
    	}
    	// 从头部遍历到index节点
    	cur := this.head
    	count := 0
    	for cur != nil {
    		if count == index {
    			break
    		}
    		count++
    		cur = cur.Next
    	}
    	return cur.Val
    }
    
    func (this *MyLinkedListD) AddAtIndex(index int, val int)  {
    	// 通过索引插入节点
    	if index > this.size {
    		return
    	}
    	// 小于0,头部插入
    	if index <= 0 {
    		this.AddAtHead(val)
    		return
    	}
    	// 尾部插入
    	if index == this.size {
    		this.AddAtTail(val)
    		return
    	}
    	// 一般情况, 找到index节点
    	cur := this.head
    	count := 0
    	for cur != nil && count < index {
    		count++
    		cur = cur.Next
    	}
    	// 生成新节点, 后继节点为cur, 前继节点为cur的前继节点,
    	// 相当于  cur.prev<---node--->cur
    	node := &Node{Val: val, Next: cur, Prev: cur.Prev}
    	cur.Prev.Next = node // cur的前继节点的下个节点指向新节点, --->
    	cur.Prev = node // cur的prev指针指向node, <---
    	// 更新size
    	this.size++
    }
    
    func (this *MyLinkedListD) AddAtHead(val int)  {
    	// 头部插入
    	node := &Node{Val: val}
    	if this.head != nil {
    		node.Next = this.head // 不断头部
    		this.head.Prev = node
    		this.head = node // 更新头部
    	} else { // 链表为空时
    		this.head = node
    		this.tail = this.head
    	}
    	// 更新size
    	this.size++
    }
    
    func (this *MyLinkedListD) AddAtTail(val int)  {
    	// 尾部插入
    	node := &Node{Val: val}
    	if this.tail != nil {
    		node.Prev = this.tail
    		this.tail.Next = node
    		this.tail = node
    	} else {
    		this.tail = node
    		this.head = this.tail
    	}
    	// 更新size
    	this.size++
    }
    
    func (this *MyLinkedListD) DeleteAtIndex(index int)  {
    	// 根据索引删除节点
    	if this.size == 0 || index < 0 || index >= this.size {
    		return
    	}
    	if index == 0 {
    		// 更新头部节点,相当于删除头结点
    		this.head = this.head.Next
    	} else if index == this.size - 1 {
    		// 更新尾部节点,相当于删除尾部节点
    		this.tail = this.tail.Prev
    	} else {
    		// 一般情况, 找到删除节点
    		cur := this.head
    		count := 0
    		for cur != nil && count < index {
    			count++
    			cur = cur.Next
    		}
    		cur.Next.Prev = cur.Prev
    		cur.Prev.Next = cur.Next
    	}
    	this.size--
    }
    
  • 相关阅读:
    黑鲨2无限重启 把竞技按钮调到最上
    绿联 电池
    阿里云
    Centos 8 搭建时钟服务器
    CentOS8系统时间同步解决方法
    解决问题的人干活快的人
    【海通国际】Joe Lowry(Mr. Lithium)谈全球电池原材料供应危机
    Linux 实验楼
    用 set follow-fork-mode child即可。这是一个 gdb 命令,其目的是告诉 gdb 在目标应用调用fork之后接着调试子进程而不是父进程,因为在 Linux 中fork系统调用成功会返回两次,一次在父进程,一次在子进程
    【随笔】阿里云修改DNS
  • 原文地址:https://www.cnblogs.com/davis12/p/15689158.html
Copyright © 2011-2022 走看看