二叉树的垂序遍历

Posted HelloCoding08

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树的垂序遍历相关的知识,希望对你有一定的参考价值。

leetcode 第987题


给你二叉树的根结点 root ,请你设计算法计算二叉树的 垂序遍历 序列。


对位于 (row, col) 的每个结点而言,其左右子结点分别位于 (row + 1, col - 1) 和 (row + 1, col + 1) 。树的根结点位于 (0, 0) 。


二叉树的 垂序遍历 从最左边的列开始直到最右边的列结束,按列索引每一列上的所有结点,形成一个按出现位置从上到下排序的有序列表。如果同行同列上有多个结点,则按结点的值从小到大进行排序。

返回二叉树的 垂序遍历 序列。


 示例 1:


输入:root = [3,9,20,null,null,15,7]

输出:[[9],[3,15],[20],[7]]

解释:

列 -1 :只有结点 9 在此列中。

列  0 :只有结点 3 和 15 在此列中,按从上到下顺序。

列  1 :只有结点 20 在此列中。

列  2 :只有结点 7 在此列中。


示例 2:


输入:root = [1,2,3,4,5,6,7]

输出:[[4],[2],[1,5,6],[3],[7]]

解释:

列 -2 :只有结点 4 在此列中。

列 -1 :只有结点 2 在此列中。

列  0 :结点 1 、5 和 6 都在此列中。

          1 在上面,所以它出现在前面。

          5 和 6 位置都是 (2, 0) ,所以按值从小到大排序,5 在 6 的前面。

列  1 :只有结点 3 在此列中。

列  2 :只有结点 7 在此列中。





#include <stdio.h>#include <stdlib.h>
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
typedef int ElemType;typedef struct node Node;typedef struct node* Tree;
struct node { ElemType elem; Node* lchild; Node* rchild;};//创建树Tree create_tree (FILE* fp) { Tree tree; ElemType elem; fscanf(fp, "%d", &elem); if (0 == elem) { return NULL; } else { tree = (Node*)malloc(sizeof(Node)); tree->elem = elem; tree->lchild = create_tree(fp); tree->rchild = create_tree(fp); } return tree;}//打印二维数组void show (int** array, int rows, const int* cols) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols[i]; j++) { printf("%d\t", array[i][j]); } printf("\n"); }}//qsort的比较函数int compare (const void* a, const void* b) { int* m = *(int**)a; int* n = *(int**)b; //先按照纵坐标排序 if (m[2] != n[2]) { return m[2] - n[2]; } //如果纵坐标相对, 再按照横坐标排序 if (m[1] != n[1]) { return m[1] - n[1]; } //如果坐标一样,再按照值排序 return m[0] - n[0];}//计算树结点的个数int get_node_nums (Tree tree) { if (tree == NULL) { return 0; } int lnode = get_node_nums(tree->lchild); int rnode = get_node_nums(tree->rchild);    //左节点的个数加上右节点的个数再加上根节点 return lnode + rnode + 1;}
void dfs (Tree tree, int rows, int cols, int** matrix, int* index) { if (tree == NULL) { return; }    //节点的值 matrix[*index][0] = tree->elem;    //节点的横坐标    matrix[*index][1] = rows;    //节点的纵坐标    matrix[*index][2] = cols; (*index)++;    dfs(tree->lchild, rows + 1, cols - 1, matrix, index);    dfs(tree->rchild, rows + 1, cols + 1, matrix, index);}
int** vertical_traversal (Tree tree, int* return_size, int** return_column_sizes) {    //创建一个3元组    //每个数组的长度都是3,    //第1个值表示节点的值,第2个和第3个值表示节点的横坐标和竖坐标    int matrix_rows = get_node_nums(tree); int* matrix_cols = (int*)malloc(sizeof(int) * matrix_rows); for (int i = 0; i < matrix_rows; i++) { matrix_cols[i] = 3; } int** matrix = (int**)malloc(sizeof(int*) * matrix_rows); for (int i = 0; i < matrix_rows; i++) { matrix[i] = (int*)malloc(sizeof(int) * matrix_cols[i]); }    //result的索引 int index = 0; //计算所有节点的值和坐标,根节点的坐标是(0,0) dfs(tree, 0, 0, matrix, &index); printf("sort before\n"); show(matrix, matrix_rows, matrix_cols); qsort(matrix, matrix_rows, sizeof(int*), compare); printf("sort after\n"); show(matrix, matrix_rows, matrix_cols);    //排序后,最大值减去最小值,总共有这么多种情况 int rows = matrix[matrix_rows - 1][2] - matrix[0][2] + 1; int** result = (int**)malloc(sizeof(int*) * rows); *return_size = 0; *return_column_sizes = (int*)malloc(sizeof(int) * rows); int i = 0; while (i < matrix_rows) { int j = i + 1; //横坐标相同的个数        int num = 1;        while (j < matrix_rows && matrix[i][2] == matrix[j][2]) { num++; j++;        } result[*return_size] = (int*)malloc(sizeof(int) * num); for (int k = 0; k < num; k++) { result[*return_size][k] = matrix[i + k][0];        } (*return_column_sizes)[*return_size] = num; (*return_size)++; i = j; } return result;}
void per_order (Tree tree) { if (tree == NULL) { return; } per_order(tree->lchild); printf("%d\t", tree->elem); per_order(tree->rchild);}
int main() { char path[] = "F:\\C\\VerticalTraversal\\987.txt"; FILE* fp = fopen(path, "r"); if (fp == NULL) { perror("file open error"); exit(-1); } Tree tree = create_tree(fp); fclose(fp); per_order(tree); printf("\n"); int rows; int* cols; int** result = vertical_traversal(tree, &rows, &cols); printf("show result\n"); show(result, rows, cols); return 0;}



以上是关于二叉树的垂序遍历的主要内容,如果未能解决你的问题,请参考以下文章

987. 二叉树的垂序遍历

987. 二叉树的垂序遍历

递归987. 二叉树的垂序遍历(困难)

[H二叉树] lc987. 二叉树的垂序遍历(dfs+哈希表)

987. 二叉树的垂序遍历

LeetCode 987. 二叉树的垂序遍历