Go语言实现链表的逆序_头插法
头插法与尾插法
头插法
概念
通过控制插入的位置,每次让新插入的结点放在头结点的后继当中,而新加入的结点还需要连接上原来头结点的原本的后继
特点
插入的顺序与最后链表形成的顺序相反(这样就可以实现自我的反转)
核心过程
p = L->next; //保存原链表的后继
L->next = NULl; //将原链表的后继置为空
//当p非空时,使用q作为插入的结点
q = p;
p = p->next; //p指针后移,用以实现后面的循环,不至于断链
q->next = L->next; //这两句实现q结点的插入
L->next = q;
Go语言实现
func Reverse(node *LNode) {
p := node.Next //保存原链表的后继
node.Next = nil //将原链表的后继置为空
for p != nil { //循环进行头插法的过程
q := p
p = p.Next //指向后面的位置,用作下一轮使用
//下面两句是用来实现头插法的
q.Next = node.Next
node.Next = q
}
}
注意:上述方法是带头指针的头插法的实现,如果是带头节点的头插法需要做一定的修改
如果是带头节点的,则说明node指向的就是第一个节点,如果不做修改则:1 2 3 4 5 -> 1 5 4 3 2 可以看到头节点上的值是没有做逆序的,方法是,可以定义一个新的节点,其next指向题目所给的node
func Reverse(node *LNode)*LNode{
newNode := &LNode{0,node}
p := head
newNode.next = nil
for p!=nil{
q:=p
p = p.next
q.next = newNode.next
newNode.next = q
}
return newNode.next
}
【注】C++实现带头节点的单链表反转
LNode* newhead;
LNode* next;
while(head!=nil){
next = head.next;
head.next = newhead;
newhead = head;
head = next;
}
return newhead;
返回值为newNode.next
尾插法(补充)
概念
将新加入的结点放在链表最后,并不断更新最后的指针,使其始终可以指向最后结点,以保证后面新结点的插入
特点
插入的顺序与最后形成链表的顺序一致
核心过程
//s作为要插入的节点,r指向最后结点
r->next = s
r = s
Go语言实现单链表反转的源码
package main
import (
"fmt"
. "github.com/isdamir/gotype"
)
//思路:可以利用头插法的特点:插入顺序与最后形成的链表顺序相反
/*
将链表中的每个位置的数据取取出来,新建一个表头
使用头插法进行插入
这样只需遍历一次原列表O(n),并且空间复杂度仅为O(1)
*/
func Reverse(node *LNode) {
p := node.Next //保存原链表的后继
node.Next = nil //将原链表的后继置为空
for p != nil { //循环进行头插法的过程
q := p
p = p.Next //指向后面的位置,用作下一轮使用
//下面两句是用来实现头插法的
q.Next = node.Next
node.Next = q
}
}
func main() {
head := &LNode{}
fmt.Println("逆序")
CreateNode(head, 8)
PrintNode("逆序前:", head)
Reverse(head)
PrintNode("逆序后:", head)
}