js算法:克拉茨猜想(一)

百度百科:克拉茨问题
bilibili:【数学狂】最容易理解的数学未解之谜 – 克拉茨猜想

实现目标

使用echarts展示树形结构,用户输入某个自然数,将该自然数的树形分支绘制出来。

实现思路

echart需要的树形数据结构

export interface EchartTree {
  name: number;
  children: EchartTree[];
}

实现一个获取数列的方法,该方法传入一个自然数

type getSequence = (n: number) => number[]

还要再实现一个方法,把获得的数列放到树形结构中。compare是一个引用,根据数列逐层比对树形数据,在需要更新数据的树形节点更新数据。

type setData = (sequence: number[], compare: EchartTree): void

具体实现

export interface EchartTree {
  name: number;
  children: EchartTree[];
}

export default class CollatzConjectureService {
  // 树形数据存到data里
  protected data: EchartTree = {
    name: 1,
    children: [],
  };

  /**
   * 直接将序列放到当前EcharTree节点
   * @param s 序列
   * @param data 比对的EcharTree节点
   */
  protected setDataDirectly(s: number[], data: EchartTree): void {
    if (s.length) {
      const tmp: EchartTree = {
        name: s.shift() as number,
        children: [],
      };
      data.children.push(tmp);
      this.setDataDirectly(s, tmp);
    }
  }

  /**
   * 将新的数列添加到树中
   * @param sequence 序列
   * @param compare 和EcharTree节点比对
   * @returns
   */
  protected setData(sequence: number[], compare: EchartTree): void {
    const num = sequence.shift();
    if (!num) {
      return;
    }
    // 最多找到一个
    const find = compare.children.find((v) => v.name === num);
    if (find) {
      // 如果找到了就继续往深处找
      this.setData(sequence, find);
    } else {
      //  如果没找到,直接将剩下的序列放到当前节点
      sequence.unshift(num);
      this.setDataDirectly(sequence, compare);
    }
  }

  getData(): EchartTree {
    return this.data;
  }

  /**
   * 获取数列,并将新的数列添加到树中
   * @param n 传入自然数
   * @returns
   */
  getSequence(n: number): number[] {
    if (!isNaN(n) && n > 0 && n % 1 === 0) {
      let result = n;
      const sequence: number[] = [n];
      //  直到算到1为止
      while (result !== 1) {
        if (result % 2 === 0) {
          result = result / 2;
        } else {
          result = result * 3 + 1;
        }
        sequence.unshift(result);
      }
      // 更新树形结构
      this.setData(sequence.slice(0), { name: 0, children: [this.data] });
      return sequence;
    } else {
      throw new Error("请传入自然数");
    }
  }
}
<template>
  <div>
    <input v-model="value" />
    <button @click="setData">set</button>
    <div id="main" />
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import CollatzConjectureService, {
  EchartTree,
} from "@/service/CollatzConjectureService";
import * as echarts from "echarts";

const service = new CollatzConjectureService();
export default defineComponent({
  name: "Test",
  data() {
    return {
      value: 1,
    };
  },
  mounted() {
    //  设置一些初始数据
    console.log(service.getSequence(32));
    console.log(service.getSequence(5));
    console.log(service.getSequence(20));
    console.log(service.getSequence(3));
    console.log(service.getSequence(80));
    console.log(service.getSequence(13));
    this.draw(service.getData());
  },
  methods: {
    setData() {
      let n = Number(this.value);
      service.getSequence(n);
      this.draw(service.getData());
    },
    draw(data: EchartTree) {
      // 基于准备好的dom,初始化echarts实例
      const myChart = echarts.init(
        document.getElementById("main") as HTMLElement
      );
      // 绘制图表
      myChart.setOption({
        tooltip: {
          trigger: "item",
          triggerOn: "mousemove",
        },
        series: [
          {
            type: "tree",
            data: [data],
            initialTreeDepth: -1,
            left: "2%",
            right: "2%",
            top: "20%",
            bottom: "8%",
            symbol: "emptyCircle",
            orient: "BT",
            expandAndCollapse: true,
            label: {
              position: "bottom",
              rotate: 90,
              verticalAlign: "middle",
              align: "right",
            },
            leaves: {
              label: {
                position: "top",
                rotate: 90,
                verticalAlign: "middle",
                align: "left",
              },
            },
            emphasis: {
              focus: "descendant",
            },
            animationDurationUpdate: 750,
          },
        ],
      });
    },
  },
});
</script>

<style scoped>
#main {
  width: 100%;
  height: 600px;
}
</style>

输出效果

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值