首页 > 其他分享 >golang面试题单向链表和双向链表

golang面试题单向链表和双向链表

时间:2023-03-20 16:14:45浏览次数:52  
标签:node golang 面试题 nil head next 链表 tail prev

甲流难受中,简单发一个链表

 

1.单项列表

package main

import (
	"fmt"
	"strconv"
)

type Node struct {
	value int
	next  *Node
}
type Linklist struct {
	len  int
	head *Node
	tail *Node
}

//构造函数linklist
func NewLinklist() *Linklist {
	return &Linklist{}
}

func (l *Linklist) Append(value int) *Linklist {
	//1.构建实例创建元素,next悬空为nil
	node := &Node{value: value}
	//node.next = nil //默认是nil
	//2.老尾巴指向node
	//2.1 如果tail为空 即一个元素也没有,tail此时为nil,nil是无法next的,head和tail都是该node.len==0,l.head=nil
	if l.tail == nil {
		l.head = node
	} else {
		//如果至少有一个元素,尾巴就可以指到下一个节点
		l.tail.next = node
	}
	//3.更新尾巴
	l.tail = node
	l.len++
	return l
}

//遍历链表取出各个元素
func (l *Linklist) Iternodes() {
	//链表头节点
	p := l.head
	for p != nil {
		fmt.Println(p)
		p = p.next
	}
}

func (n *Node) String() string {
	var s string
	if n.next == nil {
		s = "null"
	} else {
		s = strconv.Itoa(n.next.value)
	}
	return fmt.Sprintf("%d --> %s", n.value, s)
}
func main() {
	linklist := NewLinklist()
	//fmt.Println(linklist)
	l := linklist.Append(1111).Append(22)
	fmt.Println(l)

	l.Iternodes()
}

  

 

2.双向链表

 

package main

import (
	"errors"
	"fmt"
	"strconv"
)

type Node struct {
	item int
	next *Node //nil
	prev *Node //nil
}

type DoubleLinkList struct {
	len  int
	head *Node
	tail *Node
}

func NewDoubleLinkList() *DoubleLinkList {
	return &DoubleLinkList{}
}

func (n *Node) String() string {
	var s1, s2 string
	if n.next == nil {
		s1 = "null"
	} else {
		s1 = strconv.Itoa(n.next.item)
	}
	if n.prev == nil {
		s2 = "null"
	} else {
		s2 = strconv.Itoa(n.prev.item)
	}
	return fmt.Sprintf("%s<--%d--->%s", s2, n.item, s1)
}

//遍历链表取出各个元素
func (l *DoubleLinkList) Iternodes() []*Node {
	//向后遍历 找链表头节点
	p := l.head
	//复用这个for循环给insert的方法用
	nodelist := make([]*Node, 0, l.len)
	for p != nil {
		nodelist = append(nodelist, p)
		//insert方法的时候暂时注释掉该打印便于查看
		//fmt.Println(p)
		p = p.next
	}
	return nodelist
	//向后遍历 找链表尾节点
	//p = l.tail
	//for p != nil {
	//	fmt.Println(p)
	//	p = p.prev
	//}
}

//追加元素
func (l *DoubleLinkList) Append(value int) *DoubleLinkList {
	//1、构造node
	node := new(Node)
	node.item = value
	//node.next=nil  初始化默认为nil
	//node.prev=nil  初始化默认为nil

	//2、老尾巴指向node
	if l.tail == nil {
		//2.1一个元素也没有,头尾都是当前node
		l.head = node
		//l.tail = node //至少有一个的时候也会挪尾巴,抽出来
		//node.prev = nil  //l.tail,prev ==nil  //默认为nil 一个没有追加了一个,此时prev next都还是nil
		//node.next = nil  //l.tail.next ==nil  //默认不写为nil
	} else {
		//至少有一个的时候,head头不动,前一个的next指下一个,下一个的prev指前一个尾巴、其他不动
		//l.head  //尾部追加的时候头不动
		//l.tail.prev //不动
		l.tail.next = node
		node.prev = l.tail
		//node.next = nil   //默认为空
		//l.tail = node  //在没元素的时候追加一个也会挪尾巴,抽出来
	}
	//更新尾巴
	l.tail = node
	l.len++
	return l
}
func (l *DoubleLinkList) Pop() error {
	//1、没有任何元素的时候弹出错误,没有元素 即l.len==0 或 l.tail == nil 或 l.head==nil
	if l.len == 0 {
		return errors.New("empty")
	} else if l.head == l.tail {
		//只有一个元素,l.head==0xc000004090 l.tail==0xc000004090,所以上面在没有元素的时候 不推荐l.head==l.tail判断
		//上面已经把0个元素过滤掉了,所以这里l.head==l.tail做判断不会出现0个元素的情况
		//移除节点后 没有了节点 所以head和tail都是nil
		l.head = nil
		l.tail = nil
	} else {
		//不止一个元素的时候弹出
		//1、断开手拉手,即前一个(l.tail.prev)的next = nil
		//2、更新尾巴 即 l.tail = 前一个节点
		//其他不必要的手拉手 不管 即 l.tail.prev =nil l.tail.next=nil
		//前面的节点不动,更新len
		l.tail.prev.next = nil
		l.tail = l.tail.prev

	}
	l.len--
	return nil
}

func (l *DoubleLinkList) Insert(index, value int) error {
	//如果索引为负数
	if index < 0 {
		return errors.New("invalid position")
	}
	//index>0
	//定义当前节点
	var current *Node
	//Iternodes至少有一个元素的时候
	for i, node := range l.Iternodes() {
		//找到当前节点
		if index == i {
			current = node
			break
		}
		//Iternodes至少有一个元素的时候,如果遍历完Iternodes还没有和insret的索引匹配证明索引超界,那也追加
		//如果Iternodes 没有元素的时候 也会执行尾部追加 append会写两次,所以此处注释掉挪外面
		//else {
		//	l.Append(value)
		//}
	}
	//如果没找到,可能超界;也可能这个时候for循环也没走即Iternodes里没有任何元素,就尾部追加
	if current == nil {
		l.Append(value)
		return nil
	}
	//找到了插入点,一定不是尾部追加
	//分两种 1是开头插入 2是中间插入 都不会动他的尾巴
	node := new(Node)
	node.item = value
	//开头插入的条件 index=0 或current.prev = nil 或 l.head = nil
	if index == 0 {
		//当前节点的prev指到新增的节点
		current.prev = node
		//头 改成新增节点
		l.head = node
		//新头的下一个指到当前节点
		l.head.next = current //node.next = current
	} else {
		node.prev = current.prev
		node.prev.next = node
		current.prev = node
		current.prev.next = current //node.next = current

	}
	l.len++
	fmt.Println(current)
	return nil
}

func main() {
	dll := NewDoubleLinkList()
	l := dll.Append(100).Append(200).Append(300)
	fmt.Println(l)
	l.Iternodes()
	fmt.Println("=====Pop======")
	p := l.Pop()
	fmt.Println(p)
	l.Iternodes()
	fmt.Println("------insert------")
	l.Insert(1, 50)
	fmt.Println(l.Iternodes())
}

  

标签:node,golang,面试题,nil,head,next,链表,tail,prev
From: https://www.cnblogs.com/dribs/p/17236646.html

相关文章

  • [数据结构]循环链表及其基本操作
    /**@Author:*@data:2019-12-0319:47:29*@LastModifiedby:*@LastModifiedtime:2019-12-0320:00:06*/#include<iostream>#include<cstdio>usingnamesp......
  • C 链表模板及笔记
    文章目录​​Intro​​​​理解线性表的基本概念(逻辑特性、术语及物理存储)​​​​基本概念​​​​n(n>=0)个数据特性相同的元素构成的有限序列称为线性表​​​​逻辑特......
  • [数据结构]双向循环链表及其基本操作
    #include<iostream>#include<cstdio>usingnamespacestd;typedefintElem;typedefintStatus;typedefstructDulList{/*data*/Elemdata;structDulList*pri......
  • [数据结构]双向链表及其基本操作
    #include<iostream>#include<cstdio>usingnamespacestd;typedefintElem;typedefintStatus;typedefstructDulList//我猜是doubolelist...{/*data*/Elemd......
  • [数据结构]单链表及其基本操作
    /**@Author:*@data:2019-12-0214:49:03*@LastModifiedby:*@LastModifiedtime:2019-12-0215:54:49*/#include<iostream>#include<cstdio>usingnamespa......
  • [数据结构][队列]链表模拟队列操作
    #include<iostream>#include<cstdio>usingnamespacestd;#defineMAXSIZE100typedefintStatus;typedefintElem;typedefstructQNode{/*data*/Elemdata;stru......
  • [链表]用静态数组模拟单链表
    来源:模板题算法标签链表题目描述实现一个单链表,链表初始为空,支持三种操作:(1)向链表头插入一个数;(2)删除第k个插入的数后面的数;(3)在第k个插入的数后插入一个数现在要对......
  • 小心golang中的无类型常量
    对于无类型常量,可能大家是第一次听说,但这篇我就不放进拾遗系列里了。因为虽然名字很陌生,但我们每天都在用,每天都有无数潜在的坑被埋下。包括我本人也犯过同样的错误,当时代......
  • 测试开发-一天一个面试题6️⃣之接口怎么测试
    写在前面今天这个面试题可能是作为一个接口测试工程师或者服务端测试工程师面试必考的一个问题,这个问题主要考察面试者是否有过接口测试经验,能否承担一名服务端测试的工......
  • 链表
    链表的概述链表是由一个一个的节点组成,节点没有名字,每个节点从堆区空间动态申请,节点间是非连续的(物理上),但是每个节点通过指针域保存下一个节点的位置,达到逻辑上的连续......