本文件:带头结点双链表的各种操作
1.创建双链表
2.头插
3.尾插
4.显示双链表
5.按位查询
6.按位插入
7.按位删除
8.按值插入
package main
/*
本文件:带头结点双链表的各种操作
1.创建双链表
2.头插
3.尾插
4.显示双链表
5.按位查询
6.按位插入
7.按位删除
8.按值插入
*/
import (
"errors"
"fmt"
)
type Node struct {
key int
value string
pre *Node
next *Node
}
//创建一个双链表
func newDoubleList()(head *Node) {
head = &Node {
pre: nil,
next: nil,
}
return
}
//头插 传进去的newNode 的pre和next原来都是为空的
func addHeadList(head , newNode *Node) {
if head.next == nil {
//空链表的操作
head.next = newNode
newNode.pre = head
}else {
//链表非空操作
tmp := head //这个tmp是个跑龙套,为了不丢失head以至于找不到链表了(这里可以不定义tmp...)
//先让newNode分别指向前后
newNode.next = tmp.next
newNode.pre = tmp
//再操作其他两条线
newNode.next.pre = newNode
tmp.next = newNode
}
}
//尾插法
func addTailList(head,newNode *Node) {
if head.next == nil {
//空链表
head.next = newNode
newNode.pre = head
}else {
//链表非空
//找到最后一个位置,先定义一个跑龙套,以免玩坏了head以至于找不到链表
tmp := head
for tmp.next != nil {
//下移
tmp = tmp.next
}
//到了这里的时候,tmp是链表中最后的一个Node(结点)
tmp.next = newNode
newNode.pre = tmp //这里的操作和空链表的时候操作一样,可以合在一起,我想多了
}
}
//显示双链表
func showList(head *Node) {
//当进来的链表为空的时候
if head.next == nil {
fmt.Println("你想要展示的链表为空")
return
}
//定义一个跑龙套,head玩坏了,就找不到原来的链表了
tmp := head
for tmp.next != nil {
//一开始进来的就是链表的头结点
//先下移
tmp = tmp.next
//再输出值
fmt.Printf(">>key:%d,value:%s>>",tmp.key,tmp.value)
}
fmt.Println()//换行
}
//按位查询
func findByLocation(head *Node,seat int)(seatNode *Node,err error) {
if seat < 1 {
err = errors.New("输入的位置有误,不能小于1")
return
}
if head.next == nil {
err = errors.New("输入的链表为空")
return
}
//定义一个跑龙套
tmp := head
i := 0
for tmp.next != nil {
//一开始进来的是头结点
i++
tmp = tmp.next
if i == seat {
fmt.Printf("找到了,key:%d,value:%s\n",tmp.key,tmp.value)
seatNode = tmp
return
}
}
//没有找到
err = errors.New(fmt.Sprintf("链表的长度为:%d,你要查找的位置为:%d\n",i,seat))
return
}
//按位插入
func insertByLocation(head, newNode *Node, seat int) (err error){
if seat < 1 {
err = errors.New("输入的位置小于1")
return
}
//定义一个跑龙套
tmp := head
i :=0
for tmp.next != nil {
//一开始进来的是头结点
i++
tmp = tmp.next
if seat == i {
//先把新结点的指向指好
newNode.next = tmp
newNode.pre = tmp.pre
//然后将他们指向newNode
newNode.pre.next = newNode
newNode.next.pre = newNode
return
}
}
if i +1 == seat {
//插入的位置在最后
tmp.next= newNode
newNode.pre = tmp
return
}
//插入的位置过大
err = errors.New(fmt.Sprintf("链表的长度为:%d,你想插入的位置为:%d\n",i,seat))
return
}
//按位删除
func delByLocation(head *Node, seat int)(err error) {
if seat <1 {
err = errors.New("要删除的位置小于1")
return
}
if head.next == nil {
err= errors.New("链表为空")
return
}
//定义一个跑龙套
tmp := head
i :=0 //用于标识链表的位置
for tmp.next != nil {
//一开始传进来的是头结点
//所以先下移
i++
tmp = tmp.next
if seat == i {
//找到了指定要删除的那个结点
if tmp.next != nil {
//要删除的结点不是链表的最后一个结点
tmp.pre.next = tmp.next
tmp.next.pre = tmp.pre
}else {
//要删除的结点是链表的最后一个
tmp.pre.next = nil
}
return
}
}
//找不到这个位置
err = errors.New(fmt.Sprintf("链表的长度为:%d,你要删除的位置在:%d",i,seat))
return
}
//按值插入(顺序插入)
func insertByKey(head, newNode *Node) {
if head.next == nil {
//空链表
head.next = newNode
newNode.pre = head
return
}
tmp := head
for tmp.next != nil {
//一开进来的是头结点所以先下移
tmp = tmp.next
//判断key
if tmp.key> newNode.key {
//就在tmp前面插入
//先指好newNode
newNode.next = tmp
newNode.pre = tmp.pre
//然后分别指向newNo
newNode.pre.next = newNode
newNode.next.pre = newNode
return
}
}
//走到这里,代表着遍历你整个链表都找不到key比newNode.key大的,所以newNode插入到链表的最后
tmp.next = newNode
newNode.pre = tmp
}
func main() {
head := newDoubleList()
node1 := &Node{
key: 1,
value: "1111",
}
node2 := &Node{
key:2,
value: "2222",
}
node3 := &Node {
key: 3,
value: "3333",
}
//addHeadList(head, node1)
//addHeadList(head, node2)
//addHeadList(head, node3)
addTailList(head,node1)
addTailList(head,node2)
addTailList(head,node3)
showList(head)
tmp,err := findByLocation(head,1)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("-------",tmp)
//node66 := &Node{
// key: 666,
// value: "666",
//}
//err = insertByLocation(head,node66,4)
//if err != nil {
// fmt.Println(err)
// return
//}
//err = delByLocation(head,4)
//if err != nil {
// fmt.Println(err)
// return
//}
node4 := &Node{
key:4,
value: "4444",
}
node5 := &Node{
key:5,
value: "5555",
}
head2 := newDoubleList()
insertByKey(head2, node5)
insertByKey(head2, node4)
showList(head2)
}