Вопрос № 182798: Уважаемые эксперты! Помогите с программой на С++. Под ОС Windows XP, Borland Builder 6 и Visual Studio 2005. Условие задачи: Таблица реализована в виде дерева.
Вопрос № 182798:
Уважаемые эксперты! Помогите с программой на С++. Под ОС Windows XP, Borland Builder 6 и Visual Studio 2005. Условие задачи: Таблица реализована в виде дерева.
Код:
const int N=4; //Количество элементов в одном
квадрате struct element { int keyX; //Ключ 1 int keyY; //Ключ 2 char *info; //Информация };
//Узел дерева struct Node { int minX; //Нижняя граница X int maxX; //Верхняя граница X int minY; //Нижняя граница Y int maxY; //Верхняя граница Y Node *child[4]; //Массив указателей на поддеревья element *inf[N];//Массив указателей на элементы };
Написать процедуру включения нового элемента. Прим
ер вставки: В узел записываем элементы с ключами keyX, keyY (minX<keyX<maxX,minY<keyY<maxY). Одинаковой пары ключей быть не может. В каждом узле может быть не больше N элементов. После того, как N элементов было записано для соответствующего узла создаются дочерние (границы X,Y формируются в соответствии с рисунком). Далее в соответствии с границей X/Y и введенным значением ключа (keyX, keyY) - выбирается соответствующий дочерний квадрат (minX<keyX<maxX,minY<keyY<maxY). После переполнения
дочернего квадрата создаются дочерние для него.
Написать процедуру поиска информации по паре ключей. Вывод всего содержимого таблицы. Огромное спасибо!
class element { public: // Конструкторы element(int keyX, int keyY, const char* const info); element(const element& e); // Деструктор ~element(); // Оператор присваивания const element & operator=(const element& e); // Ключи int keyX() const; int keyY() const; // Данные const char* info() const; private: // Копируют аргумент в чл
ены класса void copy(const element& e); void copy(const char* const s); // Освобождает ресурсы void destroy();
int _keyX; int _keyY; char* _info; };
// Узел таблицы
class node { public: // Конструктор node(int minX, int maxX, int minY, int maxY); ~node(); // Обход всех элементов дерева с вызовом для каждого заданной функции void for_each(void (*func)(int keyX, int keyY, const char* info)); protected:
// Добавление элемента void add(const element& item); // Поиск элемента const element * find(int keyX, int keyY) const;
// Количество ветвей static const size_t _CHILD_NUM = 4; // Количество данных static const size_t _INF_NUM = 4;
Поэтому при вставке не делалось никаких дополнительных проверок на наличие элементов с такими же
ключами в таблице.
Ответ отправил: Micren (Профессор)
Ответ отправлен: 12.04.2011, 12:04
Номер ответа: 266664 Украина, Краматорск
Оценка ответа: 4
Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"?
Отправить SMS#thank 266664
на номер 1151 (Россия) |
Еще номера »
Отвечает Лысков Игорь Витальевич (Старший модератор) :
Здравствуйте, zim-zum! Программа создает дерево, случайно заполняет его элементами, выводит на экран. После чего запрашивает данные для поиска, выводит соответствующее сообщение. Выход из поиска - ввод x>=100 Что непонятно, спрашивайте
const int N=4; //Количество элементов в одном квадрате const int M=4; //Количество квадратов const int MAX_X=100; //Максимальное значение по Х const int MAX_Y=100; //Максимальное значение по Y const i
nt COUNT=50; //Число элементов
struct element { int keyX; //Ключ 1 int keyY; //Ключ 2 char *info; //Информация };
//Узел дерева struct Node { int minX; //Нижняя граница X int maxX; //Верхняя граница X int minY; //Нижняя граница Y int maxY; //Верхняя граница Y Node *child[M]; //Массив указателей на поддеревья element *inf[N]; //Массив указателей на элементы };
//рекурентная п/п освобождения памяти, занятой деревом //параметр
- адрес узла void TreeFree(Node * node) { int i;
//по всем элементам узла for (i=0; i<N; i++) { //сначала проверим, есть ли элемент if (node->inf[i]) { //есть ли поле info if (node->inf[i]->info) free(node->inf[i]->info); //освобождаем память элемента free(node->inf[i]); } } //по всем поддеревьям for (i=0; i<M; i++) { //проверим, есть ли поддере
во if (node->child[i]) //вызываем себя же с адресом поддерева TreeFree(node->child[i]); } //освобождаем память узла free(node); }
//п/п инициализации корня дерева //параметр - адрес адреса корня void TreeInit(Node ** node) { //запрашиваем память под корень //используем calloc для обнуления памяти *node = (Node*)calloc(1, sizeof Node); //зададим максимальные значения (минимальные = 0) (*node)->maxX = MAX_X; (*node)->maxY = MAX_Y; }
//п/п
добавления M пустых поддеревьев //параметр - адрес узла void TreeNodesInsert(Node * node) { //запрашиваем память сразу под все M=4 поддерева for (int i=0; i<M; i++) node->child[i] = (Node*)calloc(1, sizeof Node);
//рекурентная п/п вставки
нового элемента в дерево //параметры: адрес узла и значения x, y, info для нового элемента void TreeInsert(Node * node, int NewKeyX, int NewKeyY, char *NewInfo) { int i;
//просмотрим, есть ли место, куда записать в элементы текущего узла //по всем элементам узла for (i=0; i<N; i++) { //пустое ли место if (NULL == node->inf[i]) { //запросим память под элемент node->inf[i] = (element*)malloc(sizeof eleme
nt); //заполним информацией node->inf[i]->keyX = NewKeyX; node->inf[i]->keyY = NewKeyY; //под строку н
адо на 1 больше, чем длина (под 0) node->inf[i]->info = (char*)malloc(strlen(NewInfo)+1); strcpy(node->inf[i]->info, NewInfo); //задача выполнена - выходим return; } }
//все уже заполнено //проверим, есть ли поддеревья на данном уровне //достаточно проверить только 0-й квадрат (или все, или ни одного) if (NULL == node->child[0]) //добавляем поддеревья TreeNodesInsert(node);
//самый интересный момент :) //вычислим тндекс
поддерева, как выражение (Y выше середины)*2 + (X правее середины), //где (Y выше середины) и (X правее середины) - логические величины, равные 0 или 1 i = (NewKeyY >= (node->maxY + node->minY)/2)*2 + (NewKeyX >= (node->maxX + node->minX)/2);
//вызываем себя же, чтобы вставить элемент в поддерево TreeInsert(node->child[i], NewKeyX, NewKeyY, NewInfo); }
//рекурентная п/п вывода дерева на экран в виде: //[квадрат,]
...[квадрат,]индекс элемента x = <value>, y = <value>, xmin, xmax, ymin, ymax //x и y выводим, как ранее сформированную строку, хранимую в поле info //параметры: узел и строка, содержащая строку с квадратами предыдущих уровней void TreePrint(Node * node, char * sLevel) { int i; //строка для хранения строки с квадратами для последующего вызова char sLevelCurr[128];
//проходим по всем элементам уровня for (i=0; i<M; i++) { //проверим на наличие if
(node->inf[i]) //выводим printf("%s%d\t%s,\t\t%d\t%d,\t%d\t%d\n", sLevel, i, node->inf[i]->info, node->minX, node->maxX, node->minY, node->maxY); } //пробежимся по поддеревьям //только, если они есть if (node->child[0]) { //по всем for (i=0; i<N; i++) { //добавим к строке пройденных квадратов текущий квадрат sprintf(sLevelCurr, "%s%d,", sLevel, i);
//вызовем себя же для вывода поддерева TreePrint(node->child[i], sLevelCurr); } } }
//рекурентная п/п поиска в дерева элемента с заданными x и y //параметры: узел, x, y, адрес переменной, куда запишется адрес узла с найденным элементом //и адрес переменной, куда запишется индекс в массиве элементов //возвращается 1, если элемент найден и 0, если не найден bool TreeSearch(Node * node, int x, int y, Node ** pNode, int * pIdx) { int i;
//просмотрим массив
элементов текущего узла for (i=0; i<N; i++) { //проверим на существование и на совпадение x и y if ((node->inf[i]) && (node->inf[i]->keyX == x) && (node->inf[i]->keyY == y)) { //нашли! *pNode = node; //возвратим адрес узла *pIdx = i; //и индекс в массиве элементов return 1; //элемент найден } } //просмотрим поддеревья for (i=0; i<M; i++) { //проверим на существование
if (node->child[i]) { //вызовем себя же для проверки поддерева if (TreeSearch(node->child[i], x, y, pNode, pIdx)) //если найдено, то выходим return 1; } } //не найден! return 0; }
//основная программа int main(void) { Node *Root; //корень дерева Node *Node; //адрес узла, используется для поиска int i; //просто переменная цикла int x, y; //переменные для для заполнения и поиска по дереву int idx; //переменная для
индекса в массиве индексов, используется для поиска char string[32]; //строка для формирования поля info
//будем заполнять дерево случайными элементами //инициализация последовательности псевдослучайных чисел srand( (unsigned)time( NULL ) );
//создаем корень дерева TreeInit(&Root);
//заполняем дерево //предварительно проверяем на уникальность ключей поиском по дереву for (i=0; i<COUNT; i++) { do { x
= rand()%MAX_X; y = rand()%MAX_Y;
//если найдется, то генерим новый элемент }while (TreeSearch(Root, x, y, &Node, &id
x));
//формируем строку для info sprintf(string, "x = %d,\ty = %d", x, y); //заносим в дерево TreeInsert(Root, x, y, string); }
//выведем все элементы дерева printf("All elements of tree:\n\n"); //начинаем с корня, вторым параметром пустая строка, потому что //для корня будем выводить только индексы в массиве элементов TreePrint(Root, "");
//начинаем бесконечный цикл поиска в дереве введенных элементов //для выхода
из цикла необходимо ввести x >= 100 printf("\nSearch elements (Enter x>=100 for exit)...\n");
//циклим пока x < 100 (в начале x наверняка < 100) while(x < MAX_X) { //вводим x printf("\nEnter x: "); scanf("%d",&x); //ищем или выходим? if (x < MAX_X) { //вводим y printf("Enter y: "); scanf("%d",&y); //на всякий случай, найдем ост
аток от деления на 100 y %= MAX_Y; //ищем if (TreeSearch(Root, x, y, &Node, &idx)) { //нашли - выводим printf("%s,\t\t%d\t%d,\t%d\t%d\n", Node->inf[idx]->info, Node->minX, Node->maxX, Node->minY, Node->maxY); } else //не нашли printf("Element not found\n"); } }
//освободим память TreeFree(Root);
return 0; }
Примерный вывод программы:
----- Люби своего ближнего, как самого себя
Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
Ответ отправлен: 12.04.2011, 17:17
Номер ответа: 266675 Украина, Кировоград Тел.: +380957525051 ICQ # 234137952 Mail.ru-агент: igorlyskov@mail.ru
Оценка ответа: 5
Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"?
Отправить SMS#thank 266675
на номер 1151 (Россия) |
Еще номера »
Оценить выпуск »
Нам очень важно Ваше мнение об этом выпуске рассылки!
* Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи.
(полный список тарифов)
** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
*** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.