4.38 The larger binary trees in this chapter were generated automatically by a program. This was done by assigning an (x,y) coordinate to each tree node, drawing a circle around each coordinate (this is hard to see in come pictures), and connecting each node to its parent. Asume you have a binary search tree stored in memory (perhaps generated by one of the routines above) and that each node has two extra fields to store the coordinates.
a. The x coordinate can be computed by assigning the inorder traversal number. Write a routine to do this for each node in the tree.
b. The y coordinate can be computed by using the negative of the depth of the node. Write a rutine to do this for each node in the tree.
4.39 Write a general-purpose tree-drawing programs that will convert a tree into the following graph-assemler instructions:
a. Circle(X, Y)
b. DrawLine(i, j)
The first instruction draws a circle at (X, Y), and the second instruction connects the ith circle to the jth circle (circles are numbered in the order drawn). You should either make this a program and define some sort of input language or make this a function that can be called from any program.
//4.38 bstree.hpp
#ifndef BSTREE_HPP__
#define BSTREE_HPP__
#include <iosfwd>
const int XIncrement = 5;
const int YIncrement = -10;
template< typename Object >
class BSTree {
private:
class Node {
public:
Node(const Object& val = Object(), Node* l = NULL, Node* r = NULL,
Node* p = NULL) : parent(p), lChild(l),
rChild(r), data(val), x(0), y(0)
{}
public:
Object data;
Node* lChild;
Node* rChild;
Node* parent;
int x, y;
};
public:
BSTree() : root(NULL), parent(NULL) {}
~BSTree(){ clear(); }
BSTree(const BSTree& rhs){}
BSTree& operator=(const BSTree& rhs){}
public:
bool contains(const Object& val) const
{ return contains(val, root); }
bool empty() const
{ return root == NULL; }
void printTree(std::ostream& out)
{
if(empty())
out << "empty tree/n";
else
printTree(root, out);
}
void clear()
{ clear(root); }
void add(const Object& val)
{ insert(val, root, parent); }
void del(const Object& val)
{ remove(val, root, parent); }
void calcXCoordinate()
{
int c = 0;
calcXCoordinate(root, c);
}
void calcYCoordinate()
{
int c = 0;
calcYCoordinate(root, c);
}
private:
void insert(const Object& val, Node* &t, Node* &parent)
{
if(t == NULL)
t = new Node(val, NULL, NULL, parent);
else if(val < t->data)
insert(val, t->lChild, t);
else if(t->data < val)
insert(val, t->rChild, t);
else
return;
}
void remove(const Object& val, Node* &t, Node* &parent)
{
if(t == NULL)
return;
if(val < t->data)
remove(val, t->lChild, t);
else if(t->data < val)
remove(val, t->rChild, t);
else if(t->lChild != NULL && t->rChild != NULL)
{
t->data = findMin(t->rChild)->data;
remove(t->data, t->rChild, t);
}
else if((t->lChild != NULL && t->rChild == NULL) ||
(t->lChild == NULL && t->rChild != NULL))
{
Node* old = t;
t = (t->lChild != NULL) ? t->lChild : t->rChild;
t->parent = old->parent;
delete old;
}
else
{
t->parent->rChild == t ? t->parent->rChild = NULL :
t->parent->lChild = NULL;
delete t;
}
}
bool contains(const Object& val, Node* t) const
{
if(t == NULL)
return false;
else if(val < t->data)
return contains(val, t->lChild);
else if(t->data < val)
return contains(val, t->rChild);
else
return true;
}
static Node* findMin(Node* t)
{
if(t != NULL)
while(t->lChild != NULL)
t = t->lChild;
return t;
}
static Node* findMax(Node* t)
{
if(t != NULL)
while(t->rChild != NULL)
t = t->rChild;
return t;
}
void clear(Node* &t)
{
if(t != NULL)
{
clear(t->lChild);
clear(t->rChild);
delete t;
}
t = NULL;
}
void printTree(Node* t, std::ostream& out)
{
if(t != NULL)
{
printTree(t->lChild, out);
out << "[ " << t->x << ", "
<< t->y << " ]" << t->data << "/n";
printTree(t->rChild, out);
}
}
void calcXCoordinate(Node* t, int& count)
{
if(t != NULL)
{
calcXCoordinate(t->lChild, count);
t->x += XIncrement * (count++);
calcXCoordinate(t->rChild, count);
}
}
void calcYCoordinate(Node* t, int count)
{
if(t != NULL)
{
t->y += YIncrement * (count++);
calcYCoordinate(t->lChild, count);
calcYCoordinate(t->rChild, count);
}
}
private:
Node* root;
Node* parent;
};
#endif
//4.39 bstree.hpp
#ifndef BSTREE_HPP__
#define BSTREE_HPP__
#include <iosfwd>
class DrawTree;
const int XIncrement = 30;
const int YIncrement = 40;
template< typename Object >
class BSTree {
private:
class Node {
public:
Node(const Object& val = Object(), Node* l = NULL, Node* r = NULL,
Node* p = NULL) : parent(p), lChild(l),
rChild(r), data(val), x(10), y(10)
{}
public:
Object data;
Node* lChild;
Node* rChild;
Node* parent;
int x, y;
};
public:
BSTree() : root(NULL), parent(NULL) {}
~BSTree(){ clear(); }
BSTree(const BSTree& rhs){}
BSTree& operator=(const BSTree& rhs){}
public:
bool contains(const Object& val) const
{ return contains(val, root); }
bool empty() const
{ return root == NULL; }
void printTree(std::ostream& out)
{
if(empty())
out << "empty tree/n";
else
printTree(root, out);
}
void clear()
{ clear(root); }
void add(const Object& val)
{ insert(val, root, parent); }
void del(const Object& val)
{ remove(val, root, parent); }
void calcXCoordinate()
{
int c = 0;
calcXCoordinate(root, c);
}
void calcYCoordinate()
{
int c = 0;
calcYCoordinate(root, c);
}
private:
void insert(const Object& val, Node* &t, Node* &parent)
{
if(t == NULL)
t = new Node(val, NULL, NULL, parent);
else if(val < t->data)
insert(val, t->lChild, t);
else if(t->data < val)
insert(val, t->rChild, t);
else
return;
}
void remove(const Object& val, Node* &t, Node* &parent)
{
if(t == NULL)
return;
if(val < t->data)
remove(val, t->lChild, t);
else if(t->data < val)
remove(val, t->rChild, t);
else if(t->lChild != NULL && t->rChild != NULL)
{
t->data = findMin(t->rChild)->data;
remove(t->data, t->rChild, t);
}
else if((t->lChild != NULL && t->rChild == NULL) ||
(t->lChild == NULL && t->rChild != NULL))
{
Node* old = t;
t = (t->lChild != NULL) ? t->lChild : t->rChild;
t->parent = old->parent;
delete old;
}
else
{
t->parent->rChild == t ? t->parent->rChild = NULL :
t->parent->lChild = NULL;
delete t;
}
}
bool contains(const Object& val, Node* t) const
{
if(t == NULL)
return false;
else if(val < t->data)
return contains(val, t->lChild);
else if(t->data < val)
return contains(val, t->rChild);
else
return true;
}
static Node* findMin(Node* t)
{
if(t != NULL)
while(t->lChild != NULL)
t = t->lChild;
return t;
}
static Node* findMax(Node* t)
{
if(t != NULL)
while(t->rChild != NULL)
t = t->rChild;
return t;
}
void clear(Node* &t)
{
if(t != NULL)
{
clear(t->lChild);
clear(t->rChild);
delete t;
}
t = NULL;
}
void printTree(Node* t, std::ostream& out)
{
if(t != NULL)
{
printTree(t->lChild, out);
out << "[ " << t->x << ", "
<< t->y << " ]" << t->data << "/n";
printTree(t->rChild, out);
}
}
void calcXCoordinate(Node* t, int& count)
{
if(t != NULL)
{
calcXCoordinate(t->lChild, count);
t->x += XIncrement * (count++);
calcXCoordinate(t->rChild, count);
}
}
void calcYCoordinate(Node* t, int count)
{
if(t != NULL)
{
t->y += YIncrement * (count++);
calcYCoordinate(t->lChild, count);
calcYCoordinate(t->rChild, count);
}
}
private:
Node* root;
Node* parent;
friend class DrawTree;
};
#endif
//drawtree.hpp
#ifndef DRAWTREE_HPP__
#define DRAWTREE_HPP__
#include <windows.h>
class Point;
template < typename Object >
class BSTree;
const int Radius = 10;
class DrawTree {
public:
DrawTree();
~DrawTree();
void Draw(const HWND&);
private:
void Circle(int, int, const HWND&);
void DrawLine(const Point&, const Point&, const HWND&);
template< typename Object >
void DoDraw(const HWND&, const typename BSTree<Object>::Node*);
DrawTree(const DrawTree&);
DrawTree& operator=(const DrawTree&);
};
#endif
//treegen.hpp
#ifndef TREEGEN_HPP__
#define TREEGEN_HPP__
#include "bstree.hpp"
#include <cstdlib>
#include <vector>
#include <ctime>
template< typename Object >
void TreeGenerator(BSTree<Object>& tree, const int num)
{
std::srand(time(NULL));
std::vector<Object> vec;
int size = num;
for(int i = 1; i <= num; ++i)
{
vec.push_back(i);
}
for(int i = 0; i < num; ++i)
{
std::vector<Object>::iterator it = vec.begin();
int n = rand() % (size--);
it += n;
tree.add(*it);
vec.erase(it);
}
}
#endif
//drawtree.cpp
#include "drawtree.hpp"
#include "treegen.hpp"
#include <cstdlib>
class Point{
public:
Point(int x = NULL, int y = NULL) : x(x), y(y)
{}
public:
int x;
int y;
};
DrawTree::DrawTree()
{}
DrawTree::~DrawTree()
{}
void DrawTree::Circle(int x, int y, const HWND& hwnd)
{
HDC hdc = GetDC(hwnd);
Ellipse(hdc, x-Radius, y-Radius, x+Radius, y+Radius);
}
void DrawTree::DrawLine(const Point &from, const Point &to,
const HWND& hwnd)
{
HDC hdc = GetDC(hwnd);
MoveToEx(hdc, from.x, from.y, NULL);
LineTo(hdc,to.x, to.y);
}
void DrawTree::Draw(const HWND& hwnd)
{
BSTree<int> tree;
TreeGenerator(tree, 30);
tree.calcXCoordinate();
tree.calcYCoordinate();
DoDraw<int>(hwnd, tree.root);
}
template< typename Object >
void DrawTree::DoDraw(const HWND& hwnd, const typename BSTree<Object>::Node* t)
{
if(t != NULL)
{
Circle(t->x, t->y, hwnd);
if(t->lChild != NULL)
DrawLine(Point(t->x-Radius, t->y+Radius),
Point(t->lChild->x+Radius, t->lChild->y-Radius) ,hwnd);
if(t->rChild != NULL)
DrawLine(Point(t->x+Radius, t->y+Radius),
Point(t->rChild->x-Radius, t->rChild->y-Radius) ,hwnd);
wchar_t a[20];
_i64tow_s(t->data, a, 20, 10);
TextOut(GetDC(hwnd), t->x, t->y-Radius/2, a, wcslen(a));
DoDraw<Object>(hwnd, t->lChild);
DoDraw<Object>(hwnd, t->rChild);
}
}
//main.cpp
#include "bstree.hpp"
#include "drawtree.hpp"
#include <windows.h>
LRESULT WINAPI WndProc (HWND, UINT, WPARAM, LPARAM);
//WinMain函数
int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd; //主窗口句柄
MSG msg; //窗口消息
WNDCLASSEX wndcls; //窗口类
if ( !hPrevInstance )
{
//填充窗口类信息
wndcls.cbSize = sizeof(WNDCLASSEX);
wndcls.style = CS_HREDRAW | CS_VREDRAW; //当长或宽改变的时候重画整个窗口
wndcls.lpfnWndProc = WndProc; //长指针指向windows过程处理函数
wndcls.cbClsExtra = 0; //指明了为windows类额外分配的内存的数量,windows初始化为0
wndcls.cbWndExtra = 0; //指定了为windows实例额外分配的内存的数量,windows初始化为0
wndcls.hInstance = hInstance; //指向windows程序实例的句柄
wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION); //为了使用预先定义好的图标,需将第一个参数高为NULL
wndcls.hCursor = LoadCursor(NULL, IDC_ARROW);
wndcls.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); //背景的画刷
wndcls.lpszMenuName = NULL; //菜单
wndcls.lpszClassName = TEXT("Draw Binary Search Tree"); //指明了windows类的名称
wndcls.hIconSm = NULL;
//注册窗口类
RegisterClassEx(&wndcls);
}
//创建应用程序主窗口
hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
TEXT("Draw Binary Search Tree"),
TEXT("Tree graph"),
WS_OVERLAPPED,
0,
0,
1024,
768,
NULL,
NULL,
NULL,
NULL);
//显示窗口
ShowWindow(hWnd, SW_SHOW);
//更新主窗口客户区
UpdateWindow(hWnd);
//开始消息循环
while ( GetMessage(&msg, NULL, 0, 0) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//主窗口过程,处理窗口中各种各样的事件
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
DrawTree* dt;
switch ( msg )
{
case WM_PAINT:
dt = new DrawTree();
dt->Draw(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0); //发送退出程序的消息
break;
default:
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}