以网页形式展示二叉树

简介: 以网页形式展示二叉树

为了检验创建出来的二叉树是否正确,可以使用如下代码将二叉树以网页形式展现出来:

#define TREENODE node // 声明自定义的二叉树节点为TREENODE

#include “drawtree.h” // 包含画树代码

int main()
{

// 以网页形式展现二叉树

draw(root);
}

其中,node是自己定义的二叉树的节点的类型,root是根节点,在包含 drawtree.h 之前定义 TREENODE 这个宏为 node ,即可展示对应二叉树。

注意:

只能在linux环境下运行,windows下不可以。

代码:

#ifndef _DRAWTREE_H_
#define _DRAWTREE_H_

/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 公共头文件 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <errno.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <semaphore.h>
#include <fcntl.h>

#include <pthread.h>
/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 公共头文件 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */

#define MAX(a, b) ({ \
    typeof(a) _a = a; \
    typeof(b) _b = b; \
    (void)(&_a == &_b);\
    _a > _b? _a : _b; \
    })


/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 默认二叉树节点 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
typedef struct _tree_node
{
  int data;
  struct _tree_node *lchild;
  struct _tree_node *rchild;

#ifdef AVL
  int height;
#endif

#ifdef RB
  struct _tree_node *parent;
  int color;
#endif
}_treenode, *_linktree;
/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 默认二叉树节点 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */


/* ↓↓↓↓↓ 用户指定二叉树节点 ↓↓↓↓↓ */
#ifndef NODE
#define NODE _treenode
#endif
/* ↑↑↑↑↑ 用户指定二叉树节点 ↑↑↑↑↑ */



/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */

#ifndef QUEUE_NODE_DATATYPE
#define QUEUE_NODE_DATATYPE NODE *
#endif

typedef QUEUE_NODE_DATATYPE qn_datatype;

struct _queue_node
{
  qn_datatype data;
  struct _queue_node *next;

};

typedef struct
{
  struct _queue_node *front;
  struct _queue_node *rear;
#ifdef QUEUE_SIZE
  int size;
#endif
}_queuenode, *_linkqueue;


static _linkqueue init_queue(void)
{
    _linkqueue q = (_linkqueue)malloc(sizeof(_queuenode));
  q->front = q->rear =
    (struct _queue_node *)malloc(sizeof(struct _queue_node));
  q->rear->next = NULL;

  return q;
}

static bool is_empty_q(_linkqueue q)
{
  return (q->front == q->rear);
}

/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
static bool out_queue(_linkqueue q, qn_datatype *pdata)
{
  if(is_empty_q(q))
    return false;

  struct _queue_node *p = q->front;

  q->front = q->front->next;
  free(p);
  *pdata = q->front->data;

  return true;
}

static bool en_queue(_linkqueue q, qn_datatype data)
{
  struct _queue_node *pnew;
  pnew = (struct _queue_node *)malloc(sizeof(struct _queue_node));
  if(pnew == NULL)
    return false;

  pnew->data = data;
  pnew->next = NULL;

  q->rear->next = pnew;
  q->rear = pnew;

  return true;
}

#ifdef QUEUE_SIZE
int queue_size(_linkqueue *q)
{
  return q->size;
}
#endif
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */


static void pre_travel(NODE *root, void (*handler)(NODE *))
{
  if(root == NULL)
    return;
  
  handler(root);
  pre_travel(root->lchild, handler);
  pre_travel(root->rchild, handler);
}

static void mid_travel(NODE *root, void (*handler)(NODE *))
{
  if(root == NULL)
    return;
  
  mid_travel(root->lchild, handler);
  handler(root);
  mid_travel(root->rchild, handler);
}

static void post_travel(NODE *root, void (*handler)(NODE *))
{
  if(root == NULL)
    return;

  post_travel(root->lchild, handler);
  post_travel(root->rchild, handler);
  handler(root);
}

/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
static void level_travel(NODE *root, void (*handler)(NODE *))
{
  if(root == NULL)
    return;

    _linkqueue q;
  q = init_queue();

  en_queue(q, root);

    NODE *tmp;
  while(1)
  {
    if(!out_queue(q, &tmp))
      break;

    handler(tmp);

    if(tmp->lchild != NULL)
      en_queue(q, tmp->lchild);
    if(tmp->rchild != NULL)
      en_queue(q, tmp->rchild);
  }
}
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
static char page_begin[] = "<html><head><title>tree map"
                           "</title></head><body>"
         "<table border=0 cellspacing"
                           "=0 cellpadding=0>";
static char line_begin[] = "<tr>";
static char line_end  [] = "</tr>";
static char space     [] = "<td>&nbsp;</td>";
static char underline [] = "<td style=\"border-bottom:"
         "1px solid #58CB64\">&nbsp;"
                           "</td>";

#ifdef RB
static char data_begin_red[] = "<td bgcolor=\"#FF0000\";style="
             "\"border:1px sol"
                               "id #58CB64;background-colo"
                               "r:#DDF1D8;PADDING:2px;\" t"
                               "itle=\"level: 1\">";
static char data_begin_blk[] = "<td bgcolor=\"#000000\";style="
             "\"border:1px sol"
                               "id #58CB64;background-colo"
                               "r:#DDF1D8;PADDING:2px;\" t"
                               "itle=\"level: 1\"><font color"
        "=\"#FFFFFF\">";
static char data_end_red[] = "</td>";
static char data_end_blk[] = "</font></td>";
#else
static char data_begin[] = "<td style=\"border:1px sol"
                           "id #58CB64;background-colo"
                           "r:#DDF1D8;PADDING:2px;\" t"
                           "itle=\"level: 1\">";
static char data_end  [] = "</td>";
#endif

static char page_end  [] = "</table></body></html>";

#define MAX_NODES_NUMBER 100
#define FILENAME 32

static int central_order[MAX_NODES_NUMBER];

static void putunderline(int fd, int num)
{
  int i;
  for(i=0; i<num; i++)
  {
    write(fd, underline, strlen(underline));
  }
}


static void putspace(int fd, int num)
{
  int i;
  for(i=0; i<num; i++)
  {
    write(fd, space, strlen(space));
  }
}
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
#ifdef RB
static void putdata(int fd, NODE * p)
{
  char s[50];
  bzero(s, 50);

  snprintf(s, 50, "%d", p->data);

  switch(p->color)
  {
  case RED:
    write(fd, data_begin_red, strlen(data_begin_red));
    write(fd, s, strlen(s));
    write(fd, data_end_red, strlen(data_end_red));
    break;
  case BLACK:
    write(fd, data_begin_blk, strlen(data_begin_blk));
    write(fd, s, strlen(s));
    write(fd, data_end_blk, strlen(data_end_blk));
  }
}
#else
static void putdata(int fd, int data)
{
  char s[50];
  bzero(s, 50);

  snprintf(s, 50, "%d", data);
  write(fd, data_begin, strlen(data_begin));
  write(fd, s, strlen(s));
  write(fd, data_end, strlen(data_end));
}
#endif

static int Index = 0;
static void create_index(NODE * root)
{
  if(Index >= MAX_NODES_NUMBER-1)
    return;

  central_order[Index++] = root->data;
}


static int get_index(int data)
{
  int i;
  for(i=0; i<100; i++)
  {
    if(central_order[i] == data)
      return i;
  }
  return -1;
}

/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
static void data_leftside(int fd, NODE * root, int spaces)
{
  if(root == NULL)
    return;

  int s_line=0;

  if(root->lchild != NULL)
  {
    s_line = get_index(root->data)-
       get_index(root->lchild->data)-1;
  }
  putspace(fd, spaces-s_line);
  putunderline(fd, s_line);
}


static int data_rightside(int fd, NODE * root)
{
  if(root == NULL)
    return 0;

  int s_line=0;

  if(root->rchild != NULL)
  {
    s_line = get_index(root->rchild->data)-
       get_index(root->data)-1;
  }

  putunderline(fd, s_line);
  return s_line;
}


static void start_page(int fd)
{
  write(fd, page_begin, strlen(page_begin));
}

/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
static void end_page(int fd)
{
  write(fd, page_end, strlen(page_end));
}


static void draw(NODE * root)
{
  if(root == NULL)
    return;

  time_t t;
  time(&t);
  static char filename[FILENAME];
  bzero(filename, FILENAME);
  snprintf(filename, FILENAME, "%u.html", (unsigned)t);
  int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0644);
  if(fd == -1)
  {
    perror("open() failed");
    exit(1);
  }

  Index = 0;
  mid_travel(root, create_index);

    _linkqueue q = init_queue();

  NODE * tmp = root;
  int ndata = 1;

  start_page(fd);
  while(1)
  {
    write(fd, line_begin, strlen(line_begin));

    int i, n = 0;
    int nextline = 0;
    for(i=0; i<ndata; i++)
    {
      int index = get_index(tmp->data);

      data_leftside(fd, tmp, index-n);

      #ifdef RB
      putdata(fd, tmp);
      #else
      putdata(fd, tmp->data);
      #endif
      int rightline = data_rightside(fd, tmp);

      if(tmp->lchild != NULL)
      {
        nextline++;
        en_queue(q, tmp->lchild);
      }
      if(tmp->rchild != NULL)
      {
        nextline++;
        en_queue(q, tmp->rchild);
      }
      if(!out_queue(q, &tmp))
        return;

      n = index + rightline;
      n++;
    }
    write(fd, line_end, strlen(line_end));
    ndata = nextline;
  }
  end_page(fd);
  close(fd);
}
#endif
相关文章
|
SQL 分布式计算 DataWorks
DataWorks产品使用合集之如何开发ODPS Spark任务
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
277 2
|
Linux Go 开发工具
Golang各平台环境搭建实战
这篇文章详细介绍了如何在Windows、Linux和Mac平台上搭建Golang开发环境,包括下载和安装Go SDK、配置环境变量、安装开发工具如Visual Studio Code和Go扩展,以及如何编写和运行第一个Go程序。
491 3
|
10月前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
199 67
|
前端开发 JavaScript Android开发
跨端技术栈综合考察:深入剖析 UniApp、Flutter、Taro 和 React Native 的优势与限制
跨端技术栈综合考察:深入剖析 UniApp、Flutter、Taro 和 React Native 的优势与限制
|
JavaScript 前端开发 开发工具
使用vue3+element-ui plus 快速构建后台管理模板
本文介绍了如何使用Vue 3和Element UI Plus快速构建后台管理模板的步骤,包括安装Vue 3脚手架、Element UI Plus以及如何全局配置Element UI Plus。然后详细讲解了如何使用Element UI Plus构建布局,包括Header组件、Aside组件和HomeView视图的创建和样式调整,以及App.vue和main.css的修改,最后提供了项目的文件结构图和效果展示。
使用vue3+element-ui plus 快速构建后台管理模板
|
人工智能 API 开发者
免费使用Kimi的API接口,kimi-free-api真香
今年AI应用兴起,各类智能体涌现,但API免费额度有限。为解决这一问题,GitHub上的[kimi-free-api](https://github.com/LLM-Red-Team/kimi-free-api)项目提供了方便,支持高速流式输出、多轮对话等,与ChatGPT接口兼容。此外,还有其他大模型的免费API转换项目,如跃问StepChat、阿里通义Qwen等。该项目可帮助用户免费体验,通过Docker-compose轻松部署。只需获取refresh_token,即可开始使用。这个开源项目促进了AI学习和开发,为探索AI潜力提供了新途径。
2687 3
|
消息中间件 负载均衡 Java
如何在Java中使用Kafka
如何在Java中使用Kafka
1200 1
|
JavaScript 数据安全/隐私保护
Vue rules校验规则详解
Vue rules校验规则详解
|
机器学习/深度学习 存储 人工智能
50道必备的Python面试题 (建议点赞)
50道必备的Python面试题 (建议点赞)
8305 0
|
Go
说说Go语言for循环中的继续、中断、跳出
说说Go语言for循环中的继续、中断、跳出
307 0