数据结构课程设计(五)---输出树的路径 [树]

1.5.1 题目内容

1.5.1-A [问题描述]

****  给定一棵有N个节点(编号为1-N)的树,试输出树从根结点到所有叶结点的路径。****

1.1.1-B [基本要求]

第一行包含一个整数N,代表节点数

第二行包含N个整数p1,p2,...,pn,代表每个节点的父节点编号。若pi=0,则该节点为树的根节点

[输出数据]

输出树中从根结点到所有叶结点的路径

[输入规范]

+ 0≤pi≤N

+有且仅有一个pi=0

1 .5.2 算法思想

定义了一个树的结构体 TreeNode,其中包括节点值、子节点指针数组、子节点数量等成员变量,并且定义了打印路径函数printPaths、计算树深度函数count_tree_depth、打印树形结构函数printtree等操作函数。

在 main 函数中,首先读取输入的节点数量 n,然后根据输入的父节点和子节点的关系,构建了一个树的数据结构,并对树进行了打印路径以及打印树形结构的操作。printPaths 函数用于打印从根节点到叶子节点的所有路径,采用了递归的方式进行处理。count_tree_depth 函数用于计算树的深度,通过递归遍历树的方式实现。printtree 函数用于打印树的形状,包括树的层次结构和每个节点的值,采用了队列和哈希表的方式实现。

此外,代码中还包括了设置输出字体颜色的函数 Set_Color,用于在控制台中显示彩色输出,使界面更加清晰美观。

1 .5.3 数据结构

结构体申明如下:

1 .5.3- A VertexInfo

struct TreeNode

{

int val;

TreeNode* childs[100];

int child_num;//子节点的数量

TreeNode(int value) : val(value), child_num(0) //构造函数

{

for (int i = 0; i < 100; i++)

{

childs[i] = NULL;

}

}

};

1 .5.4 源程序 [ 260 行]
cpp 复制代码
#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
#include <Windows.h>

using namespace std;

//定义二叉树结构体 
struct TreeNode 
{
    int val;
    TreeNode* childs[100];
    int child_num;//子节点的数量 
    
    TreeNode(int value) : val(value), child_num(0) //构造函数 
	{
        for (int i = 0; i < 100; i++) 
		{
            childs[i] = NULL;
        }
    }
};

// 打印路径
void printPaths(TreeNode* root, int path_arr[], int path_len);

// 计算树的深度
void count_tree_depth(TreeNode* node, int deep);

// 打印树形结构
void printtree(TreeNode* root);

//设置字体颜色 
void Set_Color(int x);

int main() 
{
    int n;
    cout<<"请输入节点数:"<<endl;
    cin >> n;
    TreeNode* nodes[100];
    for (int i = 0; i < 100; i++) 
	{
        nodes[i] = NULL;
    }
    cout<<"请输入父节点编号:"<<endl;
    for (int i = 1; i <= n; i++) 
	{
        int parent;
        cin >> parent;
        if (nodes[i] == NULL) 
		{
            nodes[i] = new TreeNode(i);
        }
        if (parent == 0) 
		{
            nodes[0] = nodes[i];
        } else {
            if (nodes[parent] == NULL) 
			{
                nodes[parent] = new TreeNode(parent);
            }
            nodes[parent]->childs[nodes[parent]->child_num] = nodes[i];
            nodes[parent]->child_num++;
        }
    }
    int path_arr[100];
    cout<<"构建的二叉树如下:"<<endl;
    printtree(nodes[0]);
    cout << endl;
    cout<<"树中从根结点到所有叶结点的路径如下:"<<endl;
    printPaths(nodes[0], path_arr, 0);
    return 0;
}


// 打印路径
void printPaths(TreeNode* root, int path_arr[], int path_len) 
{
    if (root == NULL) 
	{
        return;
    }
    path_arr[path_len] = root->val;
    path_len++;
    if (root->child_num == 0) {
        for (int i = 0; i < path_len; i++)
		 {
            if (i > 0) 
			{
                cout << "-";
            }
            cout << path_arr[i];
        }
        cout << "、";
    } else 
	{
        for (int i = 0; i < root->child_num; i++) 
		{
            printPaths(root->childs[i], path_arr, path_len);
        }
    }
}

int tree_depth;
// 计算树的深度
void count_tree_depth(TreeNode* node, int deep) 
{
    tree_depth = deep > tree_depth ? deep : tree_depth;
    if (node->childs[0] != NULL)
        count_tree_depth(node->childs[0], deep + 1);
    if (node->childs[1] != NULL)
        count_tree_depth(node->childs[1], deep + 1);
}

// 打印树形结构
void printtree(TreeNode* root) 
{
    tree_depth = -1;
    if (root != NULL)
        count_tree_depth(root, tree_depth + 1);
    else 
	{
        cout << "****" << endl << "NULL" << endl << "****" << endl;
        return;
    }
    vector<vector<pair<int, int>>> node;
    node.resize(tree_depth + 1);
    queue<pair<TreeNode*, int>> lque;
    TreeNode* Nuptr = NULL;
    lque.push(make_pair(root, 0));
    while (1) 
	{
        TreeNode* cur = lque.front().first;
        int floor = lque.front().second;
        if (floor == tree_depth + 1)
            break;
        lque.pop();
        if (cur == NULL) 
		{
            lque.push(make_pair(Nuptr, floor + 1));
            lque.push(make_pair(Nuptr, floor + 1));
            node[floor].emplace_back(make_pair(NULL, 0));
            continue;
        }
        if (cur->childs[0] != NULL)
            lque.push(make_pair(cur->childs[0], floor + 1));
        else
            lque.push(make_pair(Nuptr, floor + 1));
        if (cur->childs[1] != NULL)
            lque.push(make_pair(cur->childs[1], floor + 1));
        else
            lque.push(make_pair(Nuptr, floor + 1));
        node[floor].emplace_back(make_pair(cur->val, 0));
    }
    unordered_map<int, vector<pair<int, int>>> hash_map;
    vector<pair<int, int>>::iterator it1;
    for (it1 = node[tree_depth].begin(); it1 != node[tree_depth].end(); it1++)
    {
        int num1 = it1 - node[tree_depth].begin() + 1;
        if (num1 % 2 == 1) {
            hash_map[(3 * num1 - 1) / 2].emplace_back(make_pair((*it1).first, tree_depth));
            (*it1).second = (3 * num1 - 1) / 2;
        }
        else {
            hash_map[(3 * num1) / 2].emplace_back(make_pair((*it1).first, tree_depth));
            (*it1).second = (3 * num1) / 2;
        }
    }
    it1--;
    int maxline = (*it1).second;

    vector<pair<int, int>>::iterator it2;
    for (int i = tree_depth - 1; i >= 0; i--) 
	{
        it1 = node[i + 1].begin();
        it2 = node[i].begin();
        while (it1 != node[i + 1].end()) 
		{
            int line1 = (*it1).second;
            it1++;
            int line2 = (*it1).second;
            it1++;
            if (it2 - node[i].begin() < node[i].size() / 2)
                (*it2).second = (line1 + line2 + 1) / 2;
            else
                (*it2).second = (line1 + line2) / 2;
            hash_map[(*it2).second].emplace_back(make_pair((*it2).first, i));
            it2++;
        }
    }
    Set_Color(2);
    cout << "*********************************************" << endl;
    for (int i = maxline; i >= 1; i--) 
	{
        vector<pair<int, int>> vec_pair = hash_map[i];
        int col = 0;
        int vec_size = vec_pair.size();
        for (int k = vec_size - 1; k >= 0; k--) 
		{
            for (; col < vec_pair[k].second; col++)
                cout << "\t";
            if (vec_pair[k].first != 0)
            {
            	Set_Color(2); 
                cout << vec_pair[k].first;
            }
            else
            {
            	Set_Color(4); 
                cout << "NULL";
            }
        }
        cout << endl;
    }
    cout << "*********************************************" << endl;
}

//设置字体颜色 
void Set_Color(int x)
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);
	//此函数可控制字体颜色,颜色对应列表如下所示
	/*
	color(0);
	printf("黑色\n");
	color(1);
	printf("蓝色\n");
	color(2);
	printf("绿色\n");
	color(3);
	printf("湖蓝色\n");
	color(4);
	printf("红色\n");
	color(5);
	printf("紫色\n");
	color(6);
	printf("黄色\n");
	color(7);
	printf("白色\n");
	color(8);
	printf("灰色\n");
	color(9);
	printf("淡蓝色\n");
	color(10);
	printf("淡绿色\n");
	color(11);
	printf("淡浅绿色\n");
	color(12);
	printf("淡红色\n");
	color(13);
	printf("淡紫色\n");
	color(14);
	printf("淡黄色\n");
	color(15);
	printf("亮白色\n");
	在0-15范围修改的是字体的颜色超过15改变的是文本背景色
	*/
}
1 .5.5 测试数据与运行结果
1 .5.5- A 测试数据

7

0 5 5 1 4 1 4

1 .5.5- B 运行结果
1 .5 . 6 时间复杂度

时间复杂度为O(n^2).

源码地址:GeekclubC/Course-Design-of-Data-Structure: 用C++完成的数据结构课程设计 (github.com)

相关推荐
luky!18 分钟前
算法--解决熄灯问题
python·算法
鸽鸽程序猿24 分钟前
【算法】【优选算法】二分查找算法(下)
java·算法·二分查找算法
_OLi_25 分钟前
力扣 LeetCode 150. 逆波兰表达式求值(Day5:栈与队列)
算法·leetcode·职场和发展
远望清一色35 分钟前
基于MATLAB身份证号码识别
开发语言·图像处理·算法·matlab
醉颜凉2 小时前
【NOIP提高组】潜伏者
java·c语言·开发语言·c++·算法
hunandede2 小时前
FFmpeg 4.3 音视频-多路H265监控录放C++开发十三.2:avpacket中包含多个 NALU如何解析头部分析
c++·ffmpeg·音视频
lapiii3582 小时前
图论-代码随想录刷题记录[JAVA]
java·数据结构·算法·图论
爱学习的大牛1232 小时前
通过vmware虚拟机安装和调试编译好的 ReactOS
c++·windows内核
Dontla3 小时前
Rust泛型系统类型推导原理(Rust类型推导、泛型类型推导、泛型推导)为什么在某些情况必须手动添加泛型特征约束?(泛型trait约束)
开发语言·算法·rust