Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Нарисовать дерево в консоле 
V
    Опции темы
Ak47black
  Дата 5.12.2009, 03:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: -1
Всего: 0



Здравствуйте.
Подскажите пожалуйста, можете кто-то уже сталкивался с чем-то подобным.
Есть простенькая программа которая реализует Binary Heap, строит дерево и сохраняет его в файл.
В векторе хранятся элементы дерева по принципу:
1 - элемент - корень
2 - элемент левый лист
3 - элемент правый лист
....
элементы с лева на право.
Вопрос:
Как тут можно изобразить(нарисовать) это дерево в консоле?
(С ипользованием псевдографики) 
Может есть какой-то уже изобретённый метод, ато даже трудно изобразить уже готовое в notepadе   smile 

main.cpp  
Код

//---------------------------------------------------------------------------

#include <vcl.h>
#include "BinaryHeap.h"
#include <iostream>
#include <fstream>


//---------------------------------------------------------------------------

int main(int argc, char* argv[])
{
    BinaryHeap heap;

    heap.insert(8);  
    heap.insert(12);
    heap.insert(17);
    heap.insert(4);
    heap.insert(8);
    heap.insert(12);
    heap.insert(2);
    heap.insert(14);
    heap.insert(3);

  


    //heap.deleteDublicates();
    heap.writeToFile("derevo.txt");


    return 0;
}
//---------------------------------------------------------------------------

BinaryHeap.h
Код

#ifndef BINARY_HEAP_H_
#define BINARY_HEAP_H_

#include "vector.h"

class BinaryHeap
{
    public:
        BinaryHeap(int capacity = 20);

        bool isEmpty( ) const;
        bool isFull( ) const;

        void insert(const int x);
        void deleteDublicates();
        void deleteElem(int num);
        void makeEmpty( );
        void writeToFile(string s);

        private:
            int currentSize;
            vector<int> array; // struktura

            void buildHeap( );
            void percolateDown( int hole );
};

#endif

BinaryHeap.cpp
Код

#include "BinaryHeap.h"

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

using namespace std;

BinaryHeap::BinaryHeap( int capacity )
          : array( capacity + 1 ), currentSize( 0 )
{

}

void BinaryHeap::insert(const int x)
{
    if( isFull( ) )
    {
        cout << "Overflow error.\n";
        return;
    }

    int hole = ++currentSize;
    for( ; hole > 1 && x < array[ hole / 2 ]; hole /= 2 )
                array[ hole ] = array[ hole / 2 ];
    array[ hole ] = x;
}



void BinaryHeap::buildHeap( )
{
    for( int i = currentSize / 2; i > 0; i-- )
        percolateDown( i );
}

bool BinaryHeap::isEmpty( ) const
{
    return currentSize == 0;
}

bool BinaryHeap::isFull( ) const
{
    return currentSize == array.size( ) - 1;
}

void BinaryHeap::makeEmpty( )
{
    currentSize = 0;
}

void BinaryHeap::percolateDown( int hole )
{
/* 1*/      int child;
/* 2*/      int tmp = array[ hole ];

/* 3*/      for( ; hole * 2 <= currentSize; hole = child )
            {
/* 4*/          child = hole * 2;
/* 5*/          if( child != currentSize && array[ child + 1 ] < array[ child ] )
/* 6*/              child++;
/* 7*/          if( array[ child ] < tmp )
/* 8*/              array[ hole ] = array[ child ];
                else
/* 9*/              break;
            }
/*10*/      array[ hole ] = tmp;
}

void BinaryHeap::deleteDublicates() 
{
    for (int i = 1; i <= currentSize; i++)
    {
        for (int ii = i+1; ii < currentSize-1; ii++)
        {
            if (array[i] == array[ii])
            {
                deleteElem(i);
                i = 0;
                ii = 0;
            }
        }
    }
}

void BinaryHeap::deleteElem(int num)
{
    array[num] = array[ currentSize ];
    array[ currentSize ] = 0;
    currentSize--;
    percolateDown(num);
}

void BinaryHeap::writeToFile(string s)
{
    ofstream f(s.c_str());
    for (int i = 1; i <= currentSize; i++)
    {
        f << array[i];
        f << " ";
    }
    f.close();
}


Это сообщение отредактировал(а) Ak47black - 5.12.2009, 04:17

Присоединённый файл ( Кол-во скачиваний: 7 )
Присоединённый файл  test.rar 1,36 Kb
PM MAIL   Вверх
586
Дата 5.12.2009, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 10
Всего: 146



Так подойдёт?
Код
#include <iostream>

void print_with_indent(int indent, const char *s)
{
    std::cout.width(indent);
    std::cout << ' ' << s << std::endl;
}

int main(int argc, char* argv[])
{
    print_with_indent(0, "aaa");
    print_with_indent(1, "bbb");
    print_with_indent(2, "ccc");
    print_with_indent(1, "ddd");
    print_with_indent(2, "eee");
    print_with_indent(0, "fff");
    print_with_indent(0, "ggg");
    print_with_indent(1, "hhh");
    print_with_indent(2, "iii");
    print_with_indent(3, "jjj");
    print_with_indent(4, "kkk");
    print_with_indent(2, "lll");
    print_with_indent(1, "mmm");
    print_with_indent(2, "nnn");
    print_with_indent(3, "ooo");
    print_with_indent(4, "ppp");
    std::cin.get();
    return 0;
}


Это сообщение отредактировал(а) 586 - 5.12.2009, 10:28
PM   Вверх
Ak47black
Дата 5.12.2009, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: -1
Всего: 0



На немного нето, что я хочу сделать.
Я вот в таком виде хотел-бы вывести
user posted image
PM MAIL   Вверх
586
Дата 5.12.2009, 15:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 10
Всего: 146



Цитата(Ak47black @  5.12.2009,  14:20 Найти цитируемый пост)
На немного нето, что я хочу сделать.
Я вот в таком виде хотел-бы вывести

Это уже графический вид, либо ACII-арт.

Проще всего вывести дерево так:
Код
5
  3
    2
    4
  8

Или так:
Код
5
|- 3
| |- 2
| \- 4
\- 8

PM   Вверх
Ak47black
Дата 5.12.2009, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: -1
Всего: 0



Вообщем сам алгоритм вывода я уже нашел, вот он
Код

typedef struct asciinode_struct asciinode;

struct asciinode_struct
{
  asciinode * left, * right;

  //length of the edge from this node to its children
  int edge_length; 
    
  int height;      

  int lablen;

  //-1=I am left, 0=I am root, 1=right   
  int parent_dir;   
                         
  //max supported unit32 in dec, 10 digits max
  char label[11];  
};


#define MAX_HEIGHT 1000
int lprofile[MAX_HEIGHT];
int rprofile[MAX_HEIGHT];
#define INFINITY (1<<20)

//adjust gap between left and right nodes
int gap = 3;  

//used for printing next node in the same level, 
//this is the x coordinate of the next char printed
int print_next;    

int MIN (int X, int Y)  
{
  return ((X) < (Y)) ? (X) : (Y);
}

int MAX (int X, int Y)  
{
  return ((X) > (Y)) ? (X) : (Y);
}

asciinode * build_ascii_tree_recursive(Tree * t) 
{
  asciinode* node;

  if (t == NULL) return NULL;

  node = (asciinode*)malloc(sizeof(asciinode));
  node->left = build_ascii_tree_recursive(t->left);
  node->right = build_ascii_tree_recursive(t->right);
  
  if (node->left != NULL) 
  {
    node->left->parent_dir = -1;
  }

  if (node->right != NULL) 
  {
    node->right->parent_dir = 1;
  }

  sprintf(node->label, "%d", t->element);
  node->lablen = strlen(node->label);

  return node;
}


//Copy the tree into the ascii node structre
asciinode * build_ascii_tree(Tree * t) 
{
  asciinode *node;
  if (t == NULL) return NULL;
  node = build_ascii_tree_recursive(t);
  node->parent_dir = 0;
  return node;
}

//Free all the nodes of the given tree
void free_ascii_tree(asciinode *node) 
{
  if (node == NULL) return;
  free_ascii_tree(node->left);
  free_ascii_tree(node->right);
  free(node);
}

//The following function fills in the lprofile array for the given tree.
//It assumes that the center of the label of the root of this tree
//is located at a position (x,y).  It assumes that the edge_length
//fields have been computed for this tree.
void compute_lprofile(asciinode *node, int x, int y) 
{
  int i, isleft;
  if (node == NULL) return;
  isleft = (node->parent_dir == -1);
  lprofile[y] = MIN(lprofile[y], x-((node->lablen-isleft)/2));
  if (node->left != NULL) 
  {
      for (i=1; i <= node->edge_length && y+i < MAX_HEIGHT; i++) 
    {
        lprofile[y+i] = MIN(lprofile[y+i], x-i);
    }
  }
  compute_lprofile(node->left, x-node->edge_length-1, y+node->edge_length+1);
  compute_lprofile(node->right, x+node->edge_length+1, y+node->edge_length+1);
}

void compute_rprofile(asciinode *node, int x, int y) 
{
  int i, notleft;
  if (node == NULL) return;
  notleft = (node->parent_dir != -1);
  rprofile[y] = MAX(rprofile[y], x+((node->lablen-notleft)/2));
  if (node->right != NULL) 
  {
      for (i=1; i <= node->edge_length && y+i < MAX_HEIGHT; i++) 
    {
        rprofile[y+i] = MAX(rprofile[y+i], x+i);
    }
  }
  compute_rprofile(node->left, x-node->edge_length-1, y+node->edge_length+1);
  compute_rprofile(node->right, x+node->edge_length+1, y+node->edge_length+1);
}

//This function fills in the edge_length and 
//height fields of the specified tree
void compute_edge_lengths(asciinode *node) 
{
  int h, hmin, i, delta;
  if (node == NULL) return;
  compute_edge_lengths(node->left);
  compute_edge_lengths(node->right);

  /* first fill in the edge_length of node */
  if (node->right == NULL && node->left == NULL) 
  {
      node->edge_length = 0;
  } 
  else 
  {
    if (node->left != NULL) 
    {
        for (i=0; i<node->left->height && i < MAX_HEIGHT; i++) 
      {
            rprofile[i] = -INFINITY;
        }
        compute_rprofile(node->left, 0, 0);
        hmin = node->left->height;
    } 
    else 
    {
        hmin = 0;
    }
      if (node->right != NULL) 
    {
        for (i=0; i<node->right->height && i < MAX_HEIGHT; i++) 
      {
            lprofile[i] = INFINITY;
        }
        compute_lprofile(node->right, 0, 0);
        hmin = MIN(node->right->height, hmin);
    } 
    else 
    {
        hmin = 0;
    }
      delta = 4;
      for (i=0; i<hmin; i++) 
    {
        delta = MAX(delta, gap + 1 + rprofile[i] - lprofile[i]);
    }
      
    //If the node has two children of height 1, then we allow the
    //two leaves to be within 1, instead of 2 
      if (((node->left != NULL && node->left->height == 1) ||
          (node->right != NULL && node->right->height == 1))&&delta>4) 
    {
      delta--;
    }
        
    node->edge_length = ((delta+1)/2) - 1;
  }

  //now fill in the height of node
  h = 1;
  if (node->left != NULL) 
  {
      h = MAX(node->left->height + node->edge_length + 1, h);
  }
  if (node->right != NULL) 
  {
      h = MAX(node->right->height + node->edge_length + 1, h);
  }
  node->height = h;
}

//This function prints the given level of the given tree, assuming
//that the node has the given x cordinate.
void print_level(asciinode *node, int x, int level) 
{
  int i, isleft;
  if (node == NULL) return;
  isleft = (node->parent_dir == -1);
  if (level == 0) 
  {
      for (i=0; i<(x-print_next-((node->lablen-isleft)/2)); i++) 
    {
        printf(" ");
    }
      print_next += i;
      printf("%s", node->label);
      print_next += node->lablen;
  } 
  else if (node->edge_length >= level) 
  {
      if (node->left != NULL) 
    {
        for (i=0; i<(x-print_next-(level)); i++) 
      {
            printf(" ");
        }
        print_next += i;
        printf("/");
        print_next++;
    }
      if (node->right != NULL) 
    {
        for (i=0; i<(x-print_next+(level)); i++) 
      {
            printf(" ");
        }
        print_next += i;
        printf("\\");
        print_next++;
    }
  } 
  else 
  {
      print_level(node->left, 
                x-node->edge_length-1, 
                level-node->edge_length-1);
      print_level(node->right, 
                x+node->edge_length+1, 
                level-node->edge_length-1);
  }
}

//prints ascii tree for given Tree structure
void print_ascii_tree(Tree * t) 
{
  asciinode *proot;
  int xmin, i;
  if (t == NULL) return;
  proot = build_ascii_tree(t);
  compute_edge_lengths(proot);
  for (i=0; i<proot->height && i < MAX_HEIGHT; i++) 
  {
      lprofile[i] = INFINITY;
  }
  compute_lprofile(proot, 0, 0);
  xmin = 0;
  for (i = 0; i < proot->height && i < MAX_HEIGHT; i++) 
  {
      xmin = MIN(xmin, lprofile[i]);
  }
  for (i = 0; i < proot->height; i++) 
  {
      print_next = 0;
      print_level(proot, -xmin, i);
      printf("\n");
  }
  if (proot->height >= MAX_HEIGHT) 
  {
      printf("(This tree is taller than %d, and may be drawn incorrectly.)\n", MAX_HEIGHT);
  }
  free_ascii_tree(proot); 
}

Большая проблема заключается теперь в том, как можно из массива (heap tree) сделать дерево
Тоесть например из массива (который получатся при выполенении моей программы)
Цитата

2 3 4 8 8 17 12 14 12 

сделать вот такое дерево
user posted image
используя стандартную структуру
Код

struct Tree

{
   Tree * left, * right;
   int element;
};

Стандартная рекурсия тут нечего недаёт.

Добавлено через 1 минуту и 57 секунд
Я немогу никак вспомнить.
Может кто помнит, какой можно применить принцип.

Добавлено через 6 минут и 31 секунду
Тоесть другими словами мне нужно взять массив (вектор vector<int> array;), взять из него 1 (array[1])элемент и сделать из него корень, потом у этого корня создать левый элемент и сделать его значение равное array[2], далее у этого корня создать правый элемент и сделать его значение равное array[3].
Или ещё другими словами так заполнять
Цитата

1
2 3
4 5
6 7 8 9
 
PM MAIL   Вверх
Ak47black
Дата 5.12.2009, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: -1
Всего: 0



Уже нашел выход через vector<Tree*> trees; извините а беспокойство.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0516 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.