lua实现链表

代码跃动客
• 阅读 3740

lua是一个简洁、轻量、可扩展的脚本语言,在国内,通常在游戏行业的程序员对它比较熟悉。在这篇文章中想用lua中的table实现一个链表。
首先,很简单地创建一个空链表list,空链表中,list持有first,last,count三个key,分别对应第一个,最后一个和链表节点个数:

function list.create()
    local list = {}
    list.first = nil
    list.last = nil
    list.count = 0
    return list
end

在创建链表的方法中,我们就能很清晰的知道链表的大致情况,比如,获取链表的长度,直接return list.count即可,判空同理。
其次,实现一些链表常用方法,push:添加到链表末尾,在这个方法中,形参list是你的目标链表,value是你要添加的节点数据,可以是各种类型,包括table,同时,我们给链表的每个节点添加了next,pre两个key,分别指向下一个节点和上一节点,其实,如果只是实现单向链表,next,pre只需要一个就好了,这里我们两个都写出来了:

function list.push(list, value)
    local item = {}
    item.value = value
    -- 当前空队列
    if list.first == nil then
        list.first = item
        list.last = item
        list.count = 1
    else 
        -- 非空队列,添加至末尾
        list.last.next = item
        item.pre = list.last
        list.last = item
        list.count = list.count + 1
    end
end`
接着我们在实现insert方法,插入一个节点至链表开头,key解释参考上面:
`--- 插入一个元素到开头
function list.insert(list, value)
    local item = {}
    item.value = value
    if list.first == nil then
        list.first = item
        list.last = item
        list.count = list.count + 1
    else
        item.next = list.first
        list.first.pre = item
        list.first = item
        list.count = list.count + 1
    end
end

有了添加节点的方法,当然就有删除节点方法,removeFirst和removeLast:

function list.removeFirst(list)
    local val = nil
    -- 空栈
    if list.count == 0 then
    -- 只有一个元素
    elseif list.count == 1 then
        val = list.first.value
        list.first = nil
        list.last = nil
        list.count = 0
    -- 多个元素,第一个有值
    elseif list.first ~= nil then
        -- 取值
        val = list.first.value
        -- 头指向第二个
        list.first = list.first.next
        -- 非空
        if list.first ~= nil then
            list.first.pre = nil
            list.count = list.count - 1
        else
            list.count = 0
        end
    end
    return val
end
--- 删除最后一个元素
function list.removeLast(list)
    local item = list.last
    if list.last ~= nil then
        -- 如果本身只有一个元素
        if list.last.pre == nil then
            list.first = nil
            list.last = nil
            list.count = 0
        else
            -- 不只一个元素
            list.last = list.last.pre
            list.last.next = nil
            list.count = list.count - 1
        end
    end
    if item ~= nil then
        return item.value
    end
end

既然是一个顺序链表,那在业务端必然有想要链表每一结点都想操作的方法,基于此,我们可以再写一个方法,实现链表中的每一个节点顺序调用同一个方法(逆序调用同理),形参func为用户传入想要执行的函数:

function list.foreach(list, func)
    local temp = list.first
    local continue = true
    while temp ~= nil and continue do
        continue = func(temp.value)
        if not continue then
            break
        end
        temp = temp.next
    end
end

一个用lua实现的链表到这就差不多结束了,在我看来,相比于c++实现的链表,lua的语法逻辑更为清晰明了,拓展性也更强,一个节点不需要局限于某一种类型,完全由用户自定义。
完整代碼:

dump--自定義輸出表方法
local stack_ = {}
local function createStack( ... )
    local t = {};
     t._count = 0
    t._first = nil
    t._end = nil
    t._next = nil
    t._last = nil
    --返回栈顶的对象
    function t:peek( ... )
        return t._first.value
    end
 
    --压栈
    function t:push( ... )
        t._count = t._count + 1
        local node = {}
        node.value = {...}
        node._next = nil
        node._last = t._first
        if not t._next then
            t._next = node
            t._first = node
            t._end = node
        else
            t._first._next = node
            t._first = node
        end
        dump(t._first.value,"插入的value == ")
    end
 
    --删除并返回栈顶的对象
    function t:pop()
        t._count = t._count - 1
        local value = t._first.value
        if not t._first._last then
            t._first = nil
            t._end = nil
            t._next = nil
            t._last = nil
        else
            t._first._last._next = nil
            t._first = t._first._last
        end
        return value
    end
 
    --获取堆栈长度
    function t:getn( ... )
        return t._count
    end
 
    --打印堆栈
    function t:print( ... )
        local node = t
        while(node._next)do
            dump(node._next.value,"value == ")
            node = node._next
        end
    end
 
    return t;
end
stack_.createStack = createStack
return stack_
点赞
收藏
评论区
推荐文章
22 22
4年前
【数据结构之链表】详细图文教你花样玩链表
【系列文章推荐阅读】0.提要钩玄文章已经介绍了链式存储结构,介绍了链式存储结构的最基本(简单)实现——单向链表。单向链表,顾名思义,它是单向的。因为单链表的每个结点只有一个数据域和一个指针域,而该指针域只存储了下一个结点的地址,所以我们只能通过某结点找到其直接后继结点,却不能通过某节点找到其直接前驱结点。此外,由于单链表到尾结点(链表的最后一
Easter79 Easter79
4年前
tbox链表list和list_entry的使用
TBOX中提供了各种列表操作:1.list:元素在内部维护的双向链表2.list\_entry:元素在外部维护的双向链表3.single\_list:元素在内部维护的单向链表4.single\_list\_entry:元素在外部维护的单向链表由于双链和单链的接口使用类似,这里主要就
浪人 浪人
4年前
利用“哨兵”“实现双链表
下面的代码用一个”哨兵“实现双链表,感觉很简洁,中间也有点绕,暂时实现,供学习之用staticNodelist_handle{&list_handle,&list_handle,};booladdNode(Nodenode){if(nodeNULL){returnf
Stella981 Stella981
4年前
Redis基本操作——队列 List(原理篇)
Redis基本操作——List(原理篇)  学习过数据结构的同学,一定对链表(LinkedList)十分的熟悉。相信我们自己也曾经使用过这种数据结构。  链表分为很多种:单向链表,双向链表,循环链表,块状链表\1(https://www.oschina.net/action/GoToLink?url
Wesley13 Wesley13
4年前
275,环形链表 II
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回null。为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从0开始)。如果 pos 是 1,则在该链表中没有环。说明:不允许修改给定的链表。示例1:输入:head3,2,0,4,pos
Stella981 Stella981
4年前
LinkedList
Base:JDK1.81、LinkedListLinkedList也是一个比较常见的数据结构,链表。在C/C中,链表也是一个典型的线性结构,链表分为单向跟双向的两种链表。在java里面的LinkedList是一个双向的链表。链表最好的好处就在于来一个数据加一个长度,没有多余的冗余,也是支
Stella981 Stella981
4年前
Redis+Lua——他叫了外援
    Redis从2.6版本开始引入对Lua脚本的支持,通过在Redis服务器中嵌入Lua环境,Redis客户端可以使用Lua脚本,直接在服务端原子的执行多个Redis命令。Lua    Lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。为
Stella981 Stella981
4年前
Linux下V4L2捕捉画面+H264压缩视频+帧缓冲显示视频————结合三个部分工作
前面三篇文章分别介绍了视频捕获、h264视频压缩、帧缓冲显示的实现,现在将他们结合起来摄像头采集到的数据,需要交给视频压缩线程、显示线程使用,那么我采用的方法是使用队列及链表来实现:1.摄像头采集到数据后,分别放入两个处理线程队列中,并将相关信息放入链表中2.两个线程处理完成数据后,调用回调函数,从链表里找到对应的节点,然后释
Wesley13 Wesley13
4年前
Java源码解析之LinkedList源码剖析(基于JDK1.8)
    学过数据结构的都知道双端队列(链表),没学过的也没有关系,下面我先介绍一下双端队列(链表),为什么要介绍它了,因为LinkedList本质上就是一个双端队列(链表)。一. 双端队列(链表)的介绍1. 如下图:双端队列(链表)中单个节点对应的结构!(https://oscimg.oschina.net/oscn
Stella981 Stella981
4年前
C#Redis列表List
转载自:https://www.cnblogs.com/5ishare/p/6291034.html一、前戏 在Redis中,List类型是按照插入顺序排序的字符串链表。和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素。在插入时,如果该键并不存在,Redis将为该键创建一个新的链表。与此相反,如果链表中所有的元
菜园前端 菜园前端
2年前
什么是链表?
原文链接:什么是链表?链表是有序的数据结构,链表中的每个部分称为节点。可以首、尾、中间进行数据存取,链表的元素在内存中不必是连续的空间,每个节点通过next指针指向下一个节点。优点链表的添加和删除不会导致其余元素位移。缺点无法根据索引快速定位元素。数组和链