powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Вывод дерева текстом в консоли
6 сообщений из 6, страница 1 из 1
Вывод дерева текстом в консоли
    #39374260
КириллН
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Приветствую! Подскажите, уважаемые знатоки, как мне выводить бинарное (для простоты) дерево в консоли текстом, используя символы ASCII? Результат ожидается - как на скрине во вложении.
Колупаюсь уже полвечера.

Таблица символов: https://pp.vk.me/c232/v232172/121/GgCOD57kFxA.jpg

Основной проблемой, КМК, является неумение (по неопытности в С++) использования соединений/конкатенаций: строка+строка, строка+симв.массив, строка+символ. Ну и формирование алгоритма на ночь глядя не дается... Всю жизнь только Windows-приложения делал (в основном WPF), с консольными у меня полный швах. :D

Ваяю: MSA 2003, mdb | VB.NET + mdb/SQL Express | 1Сv8, ТК УП | C# + FDB
...
Рейтинг: 0 / 0
Вывод дерева текстом в консоли
    #39374261
КириллН
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот, исправленная картинка ожидаемого результата.
...
Рейтинг: 0 / 0
Вывод дерева текстом в консоли
    #39374262
Товарищ младший сержант
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КириллН,

а какие данные на входе?
...
Рейтинг: 0 / 0
Вывод дерева текстом в консоли
    #39374264
КириллН
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Товарищ младший сержант,

Сейчас - генерируемое бинарное дерево.
Если вкратце:
• каждый элемент имеет по два потомка и ссылку на родителя;
• у корня родитель = NULL;
• один или оба потомка может быть NULL;
• глубина ограничена (во избежание переполнения стека, т.к. генерация - рекурсивная).
Если подробнее:
Листинг
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
#include <iostream>
#include <ctime>

using namespace std;

// Вероятность создания очередного узла (для ограничения количества сгенерированных элементов и глубины дерева), в процентах.
#define CHANCE_TO_BIRTH_CHILD_NODE 60
// Максимальная глубина вложенности дерева (во избежание переполнения стека из-за сверхглубокой рекурсии)
#define MAX_DEPTH 5

// Структура, описывающая узел (ветку или лист) бинарного дерева.
struct TreeNode {
	TreeNode *parent; // ссылка на родительский узел. У корневого узла эта ссылка равна NULL
	TreeNode *left, *right; // ссылки на левое и правое поддеревья. Для листьев эти ссылки равны NULL. Для многодетного дерева вместо этих переменных можно объявить массив
	int value; // содержимое узла
	int level; // уровень узла в глубине дерева
};

int LAST_VAL = 0; // последнее использованное значение узла; каждый новый узел получает значение на 1 больше предыдущего; этим реализуется уникальность значений

/* ======================= Вспомогательные функции ======================= */
// Функция для генерации потомка узла бинарного дерева.
// Вероятность появления потомка определяется шансом, равным CHANCE_TO_BIRTH_CHILD_NODE.
TreeNode *TryGenerateChild(TreeNode *parent) {
	if (parent->level >= MAX_DEPTH) return NULL; // если добрались до максимальной глубины - отменить создание потомка
	TreeNode *node; // ссылка на этот узел
	int gamble; // расчет попытки рождения этого потомка
	// Пробуем создать этот узел-потомок. В случае ошибки элемент будет равен NULL.
	try
	{
		gamble = rand() % 100; // генерируем случайное число 0-99
		if (gamble <= CHANCE_TO_BIRTH_CHILD_NODE) { // если это число попадает в вероятность рождения - этот потомок рождается
			node = new TreeNode();
			node->parent = parent;
			node->value = ++LAST_VAL;
			node->level = parent->level + 1;
			node->left = TryGenerateChild(node); // рожденному потомку создаем его левого потомка
			node->right = TryGenerateChild(node); // рожденному потомку создаем его правого потомка
		}
		else { // если у этого потомка НЕ получилось родиться
			node = NULL;
		}
	}
	catch (const std::exception&)
	{
		node = NULL;
	}
	return node;
}

// Функция для генерации бинарного дерева.
TreeNode *GenerateTree() {
	TreeNode *treeRoot = new TreeNode(); // создание ссылки на корень дерева
	treeRoot->parent = NULL; // выше корневого узла ничего нет
	treeRoot->value = ++LAST_VAL; // значение узла
	treeRoot->level = 1;
	treeRoot->left = TryGenerateChild(treeRoot); // создаем левое поддерево
	treeRoot->right = TryGenerateChild(treeRoot); // создаем правое поддерево
	return treeRoot;
}

/* ======================= Основные функции ======================= */
// Точка входа в программу.
void main() {
	system("cls"); // очистка окна консоли
	//setlocale(0, "rus"); // для корректного отображения кириллицы в консоли
	srand((int)time(0)); // инициализация ГПСЧ (генератора псевдослучайных чисел)
	TreeNode *tree = GenerateTree(); // генерируем бинарное дерево
	system("pause");
}

...
Рейтинг: 0 / 0
Вывод дерева текстом в консоли
    #39374271
Товарищ младший сержант
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КириллН,

Для начала реализуй метод, формирующий поток (последовательность) узлов в "отсортированном" (как на твоей картинке) виде.
Ну и метод, который выводит данные узла. Для начала - в любой читабельной форме, для контроля. А потом потихоньку доработай последний метод, добавляет перед выводом нужной число отступов и псевдографических элементов.
...
Рейтинг: 0 / 0
Вывод дерева текстом в консоли
    #39374850
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КириллНПодскажите, уважаемые знатоки, как мне выводить бинарное (для простоты) дерево в консоли текстом,Попробуйте так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
#include <assert.h>
#include <stdio.h>

struct node_t {
  node_t* left;
  node_t* right;
  int value;
};

struct node_print_state_t {
  node_print_state_t* child_state;
  bool printing_last_child;
};

node_print_state_t* _root_state = NULL;

void print_subtree(const node_t* node);

void print_tree(const node_t* root) {
  assert(_root_state == NULL);
  try {
    if (root != NULL) {
      print_subtree(root);
    }
  } catch (...) {
    // если что-то пошло не так, принудительно reset-им состояние
    _root_state = NULL;
    throw;
  }
}

void print_subtree(const node_t* node) {
  node_print_state_t* parent_state;
  if (_root_state != NULL) {
    printf(" ");
    node_print_state_t* s = _root_state;
    while (s->child_state != NULL) {
      printf(s->printing_last_child ? "  " : "| ");
      s = s->child_state;
    }
    parent_state = s;
    printf(parent_state->printing_last_child ? "L" : "+");
  } else {
    parent_state = NULL;
  }
  printf(">%i\n", node->value);

  if ((node->left != NULL) || (node->right != NULL)) { // если есть дети
    node_print_state_t s;
    if (parent_state != NULL) {
      parent_state->child_state = &s;
    } else {
      _root_state = &s;
    }
    s.child_state = NULL;

    // печатаем детей
    if (node->left != NULL) {
      s.printing_last_child = (node->right == NULL);
      print_subtree(node->left);
    }
    if (node->right != NULL) {
      s.printing_last_child = true;
      print_subtree(node->right);
    }

    if (parent_state != NULL) {
      parent_state->child_state = NULL;
    } else {
      _root_state = NULL;
    }
  }
}

int main() {
  node_t n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13;
  n1.left = &n2; n1.right = &n9; n1.value = 1;
  n2.left = &n3; n2.right = &n6; n2.value = 2;
  n3.left = &n4; n3.right = &n5; n3.value = 3;
  n4.left = NULL; n4.right = NULL; n4.value = 4;
  n5.left = NULL; n5.right = NULL; n5.value = 5;
  n6.left = &n7; n6.right = &n8; n6.value = 6;
  n7.left = NULL; n7.right = NULL; n7.value = 7;
  n8.left = NULL; n8.right = NULL; n8.value = 8;
  n9.left = &n10; n9.right = &n13; n9.value = 9;
  n10.left = &n11; n10.right = &n12; n10.value = 10;
  n11.left = NULL; n11.right = NULL; n11.value = 11;
  n12.left = NULL; n12.right = NULL; n12.value = 12;
  n13.left = NULL; n13.right = NULL; n13.value = 13;
  print_tree(&n1);
  return 0;
}

Вывод на консоль:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
>1
 +>2
 | +>3
 | | +>4
 | | L>5
 | L>6
 |   +>7
 |   L>8
 L>9
   +>10
   | +>11
   | L>12
   L>13

> вместо ▶
| вместо │
+ вместо ├
L вместо └
Обобщить на не-бинарное дерево вроде легко, просто в месте «печатаем детей» будет цикл по детям.

КириллНиспользуя символы ASCII?ASCII -- это 7-битная кодировка, она не содержит русских букв и символов псевдо-графики.

КириллНТаблица символов: https://pp.vk.me/c232/v232172/121/GgCOD57kFxA.jpg Это code page 866, 8-битная кодировка, которая является расширением ASCII. Использовалась в DOS для русского языка.
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Вывод дерева текстом в консоли
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]