拓扑排序——JS+Echats实现

拓扑排序算法主要过程:
1.创建一个数组记录每个节点的前驱节点数目。
2.运用递归,每一次递归中,找出没有前驱节点的节点,输出该节点,并做相关标记(或删去);然后找到该节点引出的连接,做相关标记(或删去)。
3.递归终止条件:所有的节点都已经被标记(或被删去),或者找不到没有前驱节点的节点。

核心代码如下:

 sort = function(){
      //找到没有前驱节点的节点
      var len_links = links.length;
      var arr_preNode = []; //存储左右节点的前驱节点数目
      //初始化
      for(var i = 0; i < 6; i++){
        arr_preNode[i] = 0;
      }

      //执行拓扑排序的递归运算
      doSort(len_links, arr_preNode);

      //运行结束后清除文本框最后的"-->"符号
      var textarea_sort = document.getElementById("textarea_sort");
      textarea_sort.value = textarea_sort.value.substring(0, textarea_sort.value.length-3);
    }

    
    //开始拓扑排序的递归运算
    function doSort(len_links, arr_preNode){
      //将没有被标记的arr_preNode的元素初始化
      for(var i = 0; i < arr_preNode.length; i++){
        if(arr_preNode[i] != "done"){
          arr_preNode[i] = 0;
        }
      }

      for(var i = 0; i < len_links; i++){
        if(links[i].pro != "0"){
          if(arr_preNode[parseInt(links[i].target)-1] != "done"){
            arr_preNode[parseInt(links[i].target)-1] ++;
          }
        }
      }

      //找到一个没有前驱节点的节点
      var node_index = null;
      for(var i = 0; i < len_links; i++){
        if(arr_preNode[i] == 0){
          node_index = i;
          break;
        }
      }

      //向文本框中输出结果
      var textarea_sort = document.getElementById("textarea_sort");
      textarea_sort.value += dataVisible[node_index].value[2] + "-->";
      
      //标记该节点
      arr_preNode[node_index] = "done";

      //标记该节点引出的相关连接
      for(var i = 0; i < len_links; i++){
        if(links[i].source == (node_index+1+"")){
          links[i].pro = "0";
        }
      }

      console.log("arr_preNode:"+ arr_preNode);
      console.log("links:"+ links);

      //终止递归的条件:arr_preNode中所有的元素都被标记
      for(var i = 0; i < arr_preNode.length; i++){
        if(arr_preNode[i] != "done"){
          doSort(len_links, arr_preNode);
        }
      }

      return;

    }

完整代码如下:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <script src="echarts.min.js"></script>
  <title></title>
  <style>
    body{
      padding:0;
      margin:0;
      background-color:#F9F9F9;
    }

    *{
      padding:0;
      margin:0;
      background-color:#F9F9F9;
    }

    .textarea_wrapper{
      position: relative;
      left: 0;
      top: 150px;
      height: 300px;
      width: 300px;
    }

    .textarea_sort{
      display: block;
      position: absolute;
      bottom: 0;
      width: 100%;
      height: 260px;
      box-sizing: border-box;
      color: #6d757a;
      font-size: 15px;
      font-family: Microsoft Yahei;
      font-weight: 600;
      line-height: 20px;
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 4px;
      outline: none;
      resize: none;
      transition: all .3s ease;
      cursor: text;
      white-space: pre-wrap;
      overflow-wrap: break-word;
      word-spacing: normal;
      text-transform: none;
      text-indent: 0px;
      text-shadow: none;
      text-rendering: auto;
    }

    .button{
      position: absolute;
      color: #fff;
      top: 0;
      font-size: 15px;
      font-weight: 600;
      height: 30px;
      width: 200px;
      line-height:30px; 
      background: #1E90FF;
      text-align: center;
      border:1px solid blue;
      border-radius: 5px;
      cursor: pointer;
      margin-left: 46px;
    }

    #mainEcharts{
      position: fixed !important;
      height: 600px;
      width: 400px;
      top:50%;
      left:50%;
      transform: translate3d(-50%,-50%,0);
    }

    .alert{
      position: fixed;
      margin: 0 auto;
      line-height: 30px;
      font-size: 20px;
      font-weight: 600;
      color: red;
      left: 50%;
      top:0;
      transform: translate3d(-50%,0,0);
    }
  </style>
</head>
<body>
  <div class="alert">
    1.所有节点均可拖拽;<br>
    2.推荐使用chrome/firefox浏览器。<br>
  </div>
   <div id="mainEcharts"></div>
   <div class="textarea_wrapper">
     <div class="button button_sort" onclick="sort()">Click me-->拓扑排序</div>
     <textarea class="textarea_sort" id="textarea_sort" cols="30" rows="10"></textarea>
   </div>
</body>

<script type="text/javascript">
    var dataVisible = [];//存放图中各个节点的数据信息
    var links = [];//存放图中各个连接

    var dataChild1=[{
      name:"1",//节点id
      symbol:"circle",//节点形状
      symbolSize:75,//节点大小
      //[x坐标,y坐标,label,颜色]
      value: [100, 100,"1","#1E90FF"], 
    }];
    var dataChild2=[{
      name:"2",//节点id
      symbol:"circle",//节点形状
      symbolSize:75,//节点大小
      //[x坐标,y坐标,label,颜色]
      value: [500, 100,"2","#1E90FF"], 
    }];
    var dataChild3=[{
      name:"3",//节点id
      symbol:"circle",//节点形状
      symbolSize:75,//节点大小
      //[x坐标,y坐标,label,颜色]
      value: [500, 400,"3","#1E90FF"], 
    }];
    var dataChild4=[{
      name:"4",//节点id
      symbol:"circle",//节点形状
      symbolSize:75,//节点大小
      //[x坐标,y坐标,label,颜色]
      value: [100, 400,"4","#1E90FF"], 
    }];
    var dataChild5=[{
      name:"5",//节点id
      symbol:"circle",//节点形状
      symbolSize:75,//节点大小
      //[x坐标,y坐标,label,颜色]
      value: [500, 800,"5","#1E90FF"], 
    }];
    var dataChild6=[{
      name:"6",//节点id
      symbol:"circle",//节点形状
      symbolSize:75,//节点大小
      //[x坐标,y坐标,label,颜色]
      value: [100, 800,"6","#1E90FF"], 
    }];
    

    //将所有节点存入dataVisible中
    dataVisible = dataVisible.concat(dataChild1)
                             .concat(dataChild2)
                             .concat(dataChild3)
                             .concat(dataChild4)
                             .concat(dataChild5)
                             .concat(dataChild6);

    var linkChild12 = [{
        source: "1",
        target: "2",
        pro: "1",
        label:{
            normal:{
                show: false,
            }
        },
        lineStyle:{
            normal:{
                width: 2,
                color: '#8B0000',
            }
        }
    }];

    var linkChild14 = [{
        source: "1",
        target: "4",
        pro: "1",
        label:{
            normal:{
                show: false,
            }
        },
        lineStyle:{
            normal:{
                width: 2,
                color: '#8B0000',
            }
        }
    }];

    var linkChild13 = [{
        source: "1",
        target: "3",
        pro: "1",
        label:{
            normal:{
                show: false,
            }
        },
        lineStyle:{
            normal:{
                width: 2,
                color: '#8B0000',
            }
        }
    }];

    var linkChild32 = [{
        source: "3",
        target: "2",
        pro: "1",
        label:{
            normal:{
                show: false,
            }
        },
        lineStyle:{
            normal:{
                width: 2,
                color: '#8B0000',
            }
        }
    }];

    var linkChild35 = [{
        source: "3",
        target: "5",
        pro: "1",
        label:{
            normal:{
                show: false,
            }
        },
        lineStyle:{
            normal:{
                width: 2,
                color: '#8B0000',
            }
        }
    }];

    var linkChild45 = [{
        source: "4",
        target: "5",
        pro: "1",
        label:{
            normal:{
                show: false,
            }
        },
        lineStyle:{
            normal:{
                width: 2,
                color: '#8B0000',
            }
        }
    }];

    var linkChild64 = [{
        source: "6",
        target: "4",
        pro: "1",
        label:{
            normal:{
                show: false,
            }
        },
        lineStyle:{
            normal:{
                width: 2,
                color: '#8B0000',
            }
        }
    }];

    var linkChild65 = [{
        source: "6",
        target: "5",
        pro: "1",
        label:{
            normal:{
                show: false,
            }
        },
        lineStyle:{
            normal:{
                width: 2,
                color: '#8B0000',
            }
        }
    }];


    links = links.concat(linkChild12)
                 .concat(linkChild13)
                 .concat(linkChild14)
                 .concat(linkChild32)
                 .concat(linkChild35)
                 .concat(linkChild45)
                 .concat(linkChild64)
                 .concat(linkChild65);


    var dataVisible_p=[];
    for(var i=0;i<dataVisible.length;i++){
       dataVisible_p[i]=new Array(); 
       for(var j=0;j<2;j++){      
       dataVisible_p[i][j]=dataVisible[i].value[j];
       }
    }

    //利用echarts框架令数据可视化
    var myChart=echarts.init(document.getElementById("mainEcharts"));
    myChart.setOption({
          xAxis: {
              min: 0,
              max: 1000,
              position: 'top',
              type: 'value',
              show:false,
              axisLine: {
                onZero: true,
                lineStyle:{
                  color:'#DCDCDC'
                }
              },
              axisLabel:{show:true},
              axisTick:{show:true},
          },
          yAxis: {
              min: 0,
              max: 800,
              inverse: true,
              type: 'value',
              show:false,  
              axisLine: {
                onZero: false,
                lineStyle:{
                  color:'#DCDCDC'
                }
              },
              axisLabel:{show:true},
              axisTick:{show:true},
              color:'#DCDCDC'
          },
          series: [
                   {
                     id: 'dataVisible',
                     type: 'graph', 
                     layout: 'none',
                     coordinateSystem: 'cartesian2d',
                     smooth: true,
                     data:dataVisible,
                     itemStyle: {
                         normal: {
                            color:function (parmas) {
                            return dataVisible[parmas.dataIndex].value[3];
                      },
                       borderColor: '#1E90FF',
                             borderWidth: 2,
                             shadowBlur: 10,
                             shadowColor: '#82dffe',
                             
                         }
                     },
                      label: {
                        normal: {
                          position: 'inside',
                          show: true,
                          formatter: function (parmas) {
                            return dataVisible[parmas.dataIndex].value[2];
                          },
                          backgroundColor: '#eee',
                          borderColor: '#555',
                          borderWidth: 2,
                          borderRadius: 5,
                          padding: 10,
                          fontSize: 18,
                          textBorderColor: '#000',
                          textBorderWidth: 3,
                          color: '#fff'
                        }
                      },
                      edgeSymbol: ['circle', 'arrow'],
                      edgeSymbolSize: [10, 20],
                      links: links
              },
           ], 
    });

    //添加节点可拖动功能
    myChart.setOption({
            series: [{
                id: 'dataVisible',
                data: dataVisible,
            }],
        
            graphic: echarts.util.map(dataVisible_p, function (item, dataIndex) {
                return {
                  id:"dataVisibleCircle"+dataIndex,
                    type: 'circle',
                    position: myChart.convertToPixel('grid', item),
                    shape: {
                        r: dataVisible[dataIndex].symbolSize/2+dataVisible[dataIndex].symbolSize/8
                    },
                    invisible: true,
                    draggable: true,
                    ondrag: echarts.util.curry(ondrag, dataIndex),
                    z: 100
               };
            })
    });

    //拖动节点
    function ondrag(dataIndex){
          var myChart=echarts.init(document.getElementById("mainEcharts"));
          dataVisible_p[dataIndex] = myChart.convertFromPixel('grid', this.position);
      
          var x = dataVisible_p[dataIndex][0];
          var y = dataVisible_p[dataIndex][1];
      
          dataVisible[dataIndex].value[0] = x;
          dataVisible[dataIndex].value[1] = y;


          myChart.setOption({
            series: [{
                id: 'dataVisible',
                data: dataVisible,
            }]
          });
    }

    //进行拓扑排序
    sort = function(){
      //找到没有前驱节点的节点
      var len_links = links.length;
      var arr_preNode = []; //存储左右节点的前驱节点数目
      //初始化
      for(var i = 0; i < 6; i++){
        arr_preNode[i] = 0;
      }

      //执行拓扑排序的递归算法
      doSort(len_links, arr_preNode);

      //运行结束后清除文本框最后的"-->"符号
      var textarea_sort = document.getElementById("textarea_sort");
      textarea_sort.value = textarea_sort.value.substring(0, textarea_sort.value.length-3);
    }

    
    //进行拓扑排序的递归算法
    function doSort(len_links, arr_preNode){
      //将没有被标记的arr_preNode的元素初始化
      for(var i = 0; i < arr_preNode.length; i++){
        if(arr_preNode[i] != "done"){
          arr_preNode[i] = 0;
        }
      }

      for(var i = 0; i < len_links; i++){
        if(links[i].pro != "0"){
          if(arr_preNode[parseInt(links[i].target)-1] != "done"){
            arr_preNode[parseInt(links[i].target)-1] ++;
          }
        }
      }

      //找到一个没有前驱节点的节点
      var node_index = null;
      for(var i = 0; i < len_links; i++){
        if(arr_preNode[i] == 0){
          node_index = i;
          break;
        }
      }

      //向文本框中输出结果
      var textarea_sort = document.getElementById("textarea_sort");
      textarea_sort.value += dataVisible[node_index].value[2] + "-->";
      
      //标记该节点
      arr_preNode[node_index] = "done";

      //标记该节点引出的相关连接
      for(var i = 0; i < len_links; i++){
        if(links[i].source == (node_index+1+"")){
          links[i].pro = "0";
        }
      }

      console.log("arr_preNode:"+ arr_preNode);
      console.log("links:"+ links);

      //终止递归的条件:arr_preNode中所有的元素都被标记
      for(var i = 0; i < arr_preNode.length; i++){
        if(arr_preNode[i] != "done"){
          doSort(len_links, arr_preNode);
        }
      }

      return;

    }
</script>
</html>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值