从零开始, 以双向链表实现 运势计算: 实现链表

195 阅读3分钟

本文已参与 「新人创作礼」 活动,一起开启掘金创作之路。

从古至今,关于运势和未来的计算都是王公贵族的爱好,我们可以从零开始, 以双向链表实现 运势计算(周易)。

0.0 需要获得每天的运势吗?

本文实现算法 主要参考 熊逸大师的说明,《当你的邻居为九五之尊》,这里做一个简单的汇总,如果有需要参考原文的请自行搜索。

占卜算卦是一个古老的方法,人们无法把握未来时,经常通过这个方法获得一些确定性的心理效应。

其社会影响深远而广泛,虽然它并不是一种完全准确的科学,但我们可以通过go实现 一个简易的占卜程序,用以了解我们的古人如何处理不确定性的。 并尝试了解其中的变化规则。

0.1 计算步骤初略

步骤

1, 产生49个数,为大衍之数为 54,实际参与计算的为 七七四十九

2, 随机 分成 两组(随机的方法非常重要,可以影响甚至决定结果), 为了可以产生正常的 三变 运算,最小12 也就是说范围是:天 12 ~ 37, 地 37 ~ 12

3, 从 天,地 随机选择一侧 取出一个 作为 人(一般在实际操作时,可以让寻求运势的人操作,以加强参与感)

4, 一变 把象征天的那组棋子数数有多少颗,数清楚之后把这个数字除以4(4象征一年四季),余数是几。

任何数字除以4,余数都只有四种可能:1、2、3、整除。如果遇到整除的情况,我们就当做余数是4。好了,现在把余数拿开。

把象征地的那组棋子照猫画虎,和“3”的做法一致。

把“2”里用来象征人的那一颗棋子,加上“3”中作为余数被拿掉的棋子,还有“4”里同样作为余数被拿掉的棋子归在一起。

得出的数字只有两种可能:不是9就是5。如果错了,你就从头再来吧。     好了,从1-5完成动作,叫做“一变”。

5, 二变,重复 24 步 6, 三变,重复 24 步,最后剩下的卡 除以 4 得出 第一爻

7, 重复 1~6 步,6次,产生 6个爻 即为 一卦 8, 解卦象

0.2 双向链表的实现

我们可以通过双向链表 存储卦象的6个爻,这样我们可以知道前后顺序,并且可以在每个节点存储变爻的值,为此实现其结构体 和 链表

//定义链表结构体
type node struct {
        number  int    //爻值
        yaobian [][]int   //三次爻变的 具体算子
        prev    *node   //前一个爻 节点
        next    *node   //后一个爻 节点
    }

//定义双向链表
type dlist struct {
        lens int
        head *node
        tail *node
    }

//链表构造函数
func makeDlist() *dlist {
        return &dlist{}
    }

//判断是否空链表 
func (this *dlist) newNodeList(n *node) bool { 

    if this.lens == 0 {
        this.head = n
        this.tail = n
        n.prev = nil
        n.next = nil
        this.lens += 1
        return true
    } else {
        Logg.Panic("not empty node list.")
    }
    return false
}


// 头部添加 节点
func (this *dlist) pushHead(n *node) bool {

    if this.lens == 0 {
        return this.newNodeList(n)
    } else {
        this.head.prev = n
        n.prev = nil
        n.next = this.head
        this.head = n
        this.lens += 1
        return true
    }
}


//  添加尾部节点,我们主要使用此方法,用以保持爻的相对位置
func (this *dlist) append(n *node) bool {

    if this.lens == 0 {
        return this.newNodeList(n)
    } else {
        this.tail.next = n
        n.prev = this.tail
        n.next = nil
        this.tail = n
        this.lens += 1
        return true
    }
}


/// 显示并返回链表的值
func (this *dlist) display() []int {
    
    numbs := []int{}
    node := this.head
    t := 0 
    for node != nil {

        Logg.Println(node.number, node.yaobian)
        numbs = append(numbs, node.number)
        t += 1
        if t >= this.lens {
            break
        }

        node = node.next
    }

    fmt.Println("length:", this.lens)
    return numbs
}

结语

本小节我们实现了 一个简单的双向链表,包括其链表节点 和 链表管理,添加和查询操作,这将在第三节运势解读中得到运用。

本文已参与 「新人创作礼」 活动,一起开启掘金创作之路。