关于数据结构和算法:数据结构与算法系列之链表操作全集三GO

30次阅读

共计 2463 个字符,预计需要花费 7 分钟才能阅读完成。

以下残缺的代码,及测试代码均可从这里获取 github

删除单向链表倒数第 n 个结点

办法一:快慢指针法
思路

删除倒数第 N 个结点,假如反过来看,要删除第 N 个节点。那么,一个指向头结点(头结点中也是一个数据结点)的指针向前挪动 N - 1 个结点后,指向的就是第 N 个结点

当初再看删除倒数第 N 个结点,假如此时有两个指针(快指针 fastPtr、慢指针 lowPtr)均指向头结点,快指针 fastPtr 向后遍历 N - 1 个结点之后,慢指针和快指针开始一起向后遍历,当快指针达到最初一个结点的时候,慢指针指向的地位,就是倒数第 N 个结点的地位

代码实现
func (list *List) DelLastNNode1(lastN int) {if lastN > list.Length() || lastN <= 0 {fmt.Println("输出的待删结点地位不非法")
        return
    }

    // 删除尾结点
    if lastN == 1 {list.RemoveLastNode()
        return
    }

    // 删除头结点
    if lastN == list.Length() {
        // 删除链表头结点
        list.headNode = list.headNode.Next
        return
    }

    lowNode := list.headNode
    fastNode := list.headNode
    prevNode := list.headNode
    fastStep := lastN-1
    for fastNode.Next != nil {
        if fastStep > 0 {
            fastNode = fastNode.Next
            fastStep--
            continue
        }
        fastNode = fastNode.Next
        prevNode = lowNode
        lowNode = lowNode.Next
    }
    prevNode.Next = lowNode.Next
}
办法二:结点地位和结点数量的关系法
思路

不晓得怎么删除倒数第 N 个结点,想方法晓得它是第几个不就行了。所以,要害是通过链表长度以及 N 来找到倒数第 N 个结点是负数第几个节点,通过观察能够失去,倒数第 N 个结点就是负数第 length-N+ 1 个结点,length 为链表长度

代码实现
func (list *List) DelLastNNode2(lastN int) {if lastN > list.Length() || lastN <= 0{fmt.Println("输出的待删结点地位不非法")
        return
    }

    length := list.Length()
    position := length-lastN+1

    if position == 1 {
        // 删除链表头结点
        list.headNode = list.headNode.Next
    } else if position == length {
        // 删除链表的尾结点
        list.RemoveLastNode()} else {
        // 删除链表中指定地位的结点
        list.RemovePosition(position)
    }
}

阐明:删除单链表头结点、尾结点、指定地位的节点实现,能够参考我的这一篇文章,或者这里

https://github.com/Rain-Life/data-struct-by-go

两个有序的单链表合并

该题也是 LeetCode 上第 21 题

办法一:惯例办法
思路

惯例思路就是,创立一个新的链表,而后遍历待合并的两个链表,比拟遍历到的两个结点值的大小,假如要合并之后的链表依照从小到大排序,值小的那个结点插入到新的链表中,并将值小的那个结点向后遍历一位,值大的那个结点放弃不变,而后持续比拟,反复上边步骤,如图 (留神:为了展现过程,下图中未思考链表是否为空的状况)

代码实现
func (list *List) MergeLinkedList(list1 List, list2 List) {
    if list1.HeadNode == nil && list2.HeadNode == nil {fmt.Println("两个链表均为空")
        return
    } else if list1.HeadNode == nil {
        list.HeadNode = list2.HeadNode
        return
    } else if list2.HeadNode == nil {
        list.HeadNode = list1.HeadNode
        return
    }

    curr1 := list1.HeadNode
    curr2 := list2.HeadNode
    if curr1.Data.(int) < curr2.Data.(int) {
        list.HeadNode = curr1
        curr1 = curr1.Next
    } else {
        list.HeadNode = curr2
        curr2 = curr2.Next
    }
    newHead := list.HeadNode
    currNew := newHead

    for curr1 != nil && curr2 != nil {if curr1.Data.(int) < curr2.Data.(int) {
            currNew.Next = curr1
            curr1 = curr1.Next
        } else {
            currNew.Next = curr2
            curr2 = curr2.Next
        }
        currNew = currNew.Next
    }

    if curr1 == nil {currNew.Next = curr2}
    if curr2 == nil {currNew.Next = curr1}
}
办法二:递归
思路

将上边的惯例解法用递归来实现,次要是递归的终止条件

代码实现
func RecursionMergeList(head1 *Node, head2 *Node) *Node {newNode := &Node{}
    if head1 == nil {return head2} else if head2 == nil {return head1} else {if head1.Data.(int) < head2.Data.(int) {
            newNode = head1
            newNode.Next = RecursionMergeList(head1.Next, head2)
        } else {
            newNode = head2
            newNode.Next = RecursionMergeList(head1, head2.Next)
        }
        return newNode
    }
}

正文完
 0