Название: multiple definition of
Отправлено: sandurlay от Апреля 28, 2011, 21:00
Здравствуйте. Код не мой, использую в курсовой. Все работало, но стоило мне убрать все шаблоны и сделать строго QString - как стало выдаваться "multiple definition of" на каждый метод. Сунул хидером в пустой проект - тоже самое. Помогите. #ifndef AVLTREE_H #define AVLTREE_H
///#include "math.h" #include "QString"
#define LEFTHEAVY -1 #define RIGHTHEAVY 1 #define BALANCED 0
class AVLTree; class AVLTreeGraph;
class AVLTreeNode { // Элемент дерева
protected:
AVLTreeNode* left; // Левое поддерево AVLTreeNode* right; // Правое поддерево signed char Balance; // Разность высот левого и правого поддеревьев. friend class AVLTree; friend class AVLTreeGraph;
public: int key; // Ключ QString data;
AVLTreeNode(int Key, QString Data) { // Конструктор key = Key; data = Data; left = NULL; right = NULL; Balance = 0; } };
class AVLTree {
protected:
AVLTreeNode* root; // Вершина дерева // Корень int size; // Размер дерева // Размер дерева (=количество элементов)
void InsertNode(AVLTreeNode* &cur_root,AVLTreeNode* node, int &reviseBalancefactor); // Фактическия вставка void DeleteTree(AVLTreeNode* &node); // Удаляет все элементы начиная с текущего AVLTreeNode* _find(int key,AVLTreeNode* start_pos); // Фактический рекурсивный поиск void DelNode(AVLTreeNode* &cur_root, int key, int &reviseBalancefactor); // Удалить по ключу
void SingleRotateLeft (AVLTreeNode* &p); // Одиночное вращение налево void SingleRotateRight (AVLTreeNode* &p); // Одиночное вращение направо void DoubleRotateLeft (AVLTreeNode* &p); // Двойное вращение налево void DoubleRotateRight (AVLTreeNode* &p); // Двойное вращение направо void UpdateLeftTree (AVLTreeNode* &tree, int &reviseBalanceFactor); // Балансировать левое дерево void UpdateRightTree (AVLTreeNode* &tree, int &reviseBalanceFactor); // Балансировать правое дерево
void CopyNode(AVLTreeNode* &Cur, AVLTreeNode* const &Another); // Копирование дерева AVLTreeNode* RemoveLastRight(AVLTreeNode* &cur_root, int &reviseBalancefactor); // Отсекает самый правый узел и возвращает указатель на него.
int _getHigh(AVLTreeNode* el); // Рекурсивное получение высоты дерева
friend class AVLTreeGraph;
public:
AVLTree(); // Конструктор AVLTree(int Key, QString FirstEl); // Еще конструктор virtual ~AVLTree(); // Деструктор
int getSize(); // Получить размер дерева
virtual int getHigh(); // Получить высоту дерева virtual void Insert(int Key, QString Data); // Добавить элемент virtual void Delete(int Key); // Удаление элемента по ключу AVLTreeNode* Find(int Key); // Поиск void clear(); // Очистка дерева };
// Конструктор ================================================================================================ AVLTree::AVLTree() { root = NULL; size = 0; }
// Еще конструктор ================================================================================================ AVLTree::AVLTree(int Key, QString FirstEl) { root = new AVLTreeNode(Key, FirstEl); root->left = NULL; root->right = NULL; root->Balance = BALANCED; size = 1; }
// Деструктор ================================================================================================ AVLTree::~AVLTree() { DeleteTree(root); root = NULL; size = 0; }
// Очистка дерева ================================================================================================ void AVLTree::clear() { DeleteTree(root); }
// Получение размера дерева ======================================================================================== int AVLTree::getSize() { return size; }
// Добавить элемент ======================================================================================== void AVLTree::Insert(int Key, QString Data) { if (root == NULL) { root = new AVLTreeNode(Key, Data); root->Balance = BALANCED; root->left = NULL; root->right = NULL; size = 1; return; }
AVLTreeNode* cur_root = root, *new_node = new AVLTreeNode(Key, Data);
new_node->left = NULL; new_node->right = NULL; new_node->Balance = BALANCED;
int reviseBalancefactor = 0; // флаг, используемый функцией AVLInsert для перебалансировки узлов
InsertNode(cur_root, new_node, reviseBalancefactor); // Фактическая вставка
root = cur_root; size++; }
// Получаение высоты дерева ======================================================================================== int AVLTree::getHigh() { return _getHigh(root); }
// Получаение высоты дерева ======================================================================================== int AVLTree::_getHigh(AVLTreeNode* el) { if (el == NULL) return 0; return 1 + std::max(_getHigh(el->left), _getHigh(el->right)); }
// Фактичекое добавление элемента ================================================================================================= void AVLTree::InsertNode(AVLTreeNode* &cur_root, AVLTreeNode* new_node, int &reviseBalancefactor) { int rebalanceCurrNode; // флаг "Показатель сбалансированности был изменен"
// встретилось пустое поддерево. Пора вставлять новый узел if (cur_root == NULL) { cur_root = new_node; reviseBalancefactor = 1; } else { if(new_node->key < cur_root->key) { // Спускаться по левому поддереву, если новый узел меньше текущего InsertNode(cur_root->left, new_node, rebalanceCurrNode); if(rebalanceCurrNode) { // проверить, нужно ли корректировать balanceFactor if (cur_root->Balance == LEFTHEAVY) //мы вставляем в левое поддерево, да еще в и лево перевешивает, следовательно однозначно нужно подправить дерево. UpdateLeftTree(cur_root, reviseBalancefactor); else if(cur_root->Balance == RIGHTHEAVY) { // вставка слева от узла, перевешивающего вправо. cur_root->Balance = BALANCED; reviseBalancefactor = 0; } else { cur_root->Balance = LEFTHEAVY; reviseBalancefactor = 1; } } else reviseBalancefactor = 0; } else if (new_node->key > cur_root->key) { // иначе рекурсивно спускаться по правому поддереву InsertNode(cur_root->right, new_node, rebalanceCurrNode); if(rebalanceCurrNode) { // проверить, нужно ли корректировать balanceFactor if (cur_root->Balance == RIGHTHEAVY)//мы вставляем в правое поддерево, да еще в и право перевешивает, следовательно однозначно нужно подправить дерево. UpdateRightTree(cur_root, reviseBalancefactor); else if(cur_root->Balance==LEFTHEAVY) { //вставка справа от узла,перевешивающего влево=> узел станет сбалансированным cur_root->Balance = BALANCED; reviseBalancefactor = 0; } else { cur_root->Balance = RIGHTHEAVY; reviseBalancefactor = 1; } } else reviseBalancefactor = 0; } } }
// Удаление элемента по ключу ======================================================================================== void AVLTree::Delete(int Key) { int reviseBalancefactor = 0; DelNode(root, Key, reviseBalancefactor); }
// Поиск элемента ======================================================================================== AVLTreeNode* AVLTree::Find(int Key) { return _find(Key, root); }
// Одиночное вращение налево ============================================================================== void AVLTree::SingleRotateLeft (AVLTreeNode* &p) { AVLTreeNode *rc = p->right; p->Balance = BALANCED; rc->Balance = BALANCED; p->right = rc->left; rc->left = p; p = rc; }
// Одиночное вращение направо ============================================================================== void AVLTree::SingleRotateRight (AVLTreeNode* &p) { AVLTreeNode *lc; lc = p->left; p->Balance = BALANCED; lc->Balance = BALANCED; p->left = lc->right; lc->right = p; p = lc; }
// Двойное вращение налево ============================================================================== void AVLTree::DoubleRotateLeft (AVLTreeNode* &p) { AVLTreeNode *rc = p->right, *np = rc->left;
if (np == NULL) return;
if(np->Balance == LEFTHEAVY) { p->Balance = BALANCED; rc->Balance = RIGHTHEAVY; } else { p->Balance = LEFTHEAVY; rc->Balance = BALANCED; }
np->Balance = BALANCED; rc->left = np->right; np->right = rc; p->right = np->left; np->left = p; p = np; }
// Двойное вращение направо ============================================================================== void AVLTree::DoubleRotateRight (AVLTreeNode* &p) { AVLTreeNode *lc = p->left, *np = lc->right;
if (np->Balance == RIGHTHEAVY) { p->Balance = BALANCED; lc->Balance = LEFTHEAVY; } else { p->Balance = RIGHTHEAVY; lc->Balance = BALANCED; }
np->Balance = BALANCED; lc->right = np->left; np->left = lc; p->left = np->right; np->right = p; p = np; }
// Балансировка левого дерева ============================================================================== void AVLTree::UpdateLeftTree (AVLTreeNode* &tree, int &reviseBalanceFactor) { AVLTreeNode *lc; lc = tree->left;
if (lc->Balance == LEFTHEAVY) { // перевешивает левое поддерево? SingleRotateRight(tree); // однократный поворот reviseBalanceFactor = 0; } else { if (lc->Balance == BALANCED) { DoubleRotateRight(tree); // выполнить двойной поворот tree->Balance = LEFTHEAVY; lc->Balance = LEFTHEAVY; reviseBalanceFactor = 1; } else { DoubleRotateRight(tree); // выполнить двойной поворот reviseBalanceFactor = 0; // теперь корень уравновешен } } }
// Балансировка правого дерева ============================================================================== void AVLTree::UpdateRightTree (AVLTreeNode* &tree, int &reviseBalanceFactor) { AVLTreeNode *rc; rc=tree->right;
if (rc->Balance == RIGHTHEAVY) { //перевешивает ли правое поддерево? SingleRotateLeft(tree); reviseBalanceFactor=0; } else { if (rc->Balance == BALANCED) { DoubleRotateLeft(tree); tree->Balance = RIGHTHEAVY;//при двойном попороте, при условии, что правый сын сбалансирован перекосы становятся вправо. rc->Balance = RIGHTHEAVY; reviseBalanceFactor = 1; } else { DoubleRotateLeft(tree); reviseBalanceFactor = 0; } } }
// Удалить начиная с текущего ============================================================================== void AVLTree::DeleteTree(AVLTreeNode* &node) { if (node == NULL) return;
if (node->left != NULL) DeleteTree(node->left);
if (node->right != NULL) DeleteTree(node->right);
delete[] node;
node = NULL; size = 0; }
// Рекурсивный поиск ======================================================================================= AVLTreeNode* AVLTree::_find(int key, AVLTreeNode* start_pos) { if (start_pos==0) { //throw err("There is no such element in tree"); return NULL; }
if (start_pos->key == key) return start_pos;
if(key < start_pos->key) return _find(key, start_pos->left); else return _find(key, start_pos->right); }
// Фактическое удаление по ключу ======================================================================= void AVLTree::DelNode(AVLTreeNode* &cur_root, int key, int &reviseBalancefactor) {
if (cur_root == 0) { reviseBalancefactor = 0; return; }
int rebalanceCurNode; if (key < cur_root->key) { DelNode(cur_root->left, key, rebalanceCurNode);
if(rebalanceCurNode) { if(cur_root->Balance == RIGHTHEAVY) { UpdateRightTree(cur_root,reviseBalancefactor); reviseBalancefactor = !reviseBalancefactor; } else if(cur_root->Balance == BALANCED) { cur_root->Balance = RIGHTHEAVY; reviseBalancefactor = 0; } else { cur_root->Balance = BALANCED; reviseBalancefactor = 1; } } else reviseBalancefactor = 0; } else if (key > cur_root->key) {
DelNode(cur_root->right,key,rebalanceCurNode);
if (rebalanceCurNode) { if (cur_root->Balance == LEFTHEAVY) { UpdateLeftTree(cur_root, reviseBalancefactor); reviseBalancefactor = !reviseBalancefactor; } else if (cur_root->Balance == BALANCED) { cur_root->Balance = LEFTHEAVY; reviseBalancefactor = 0; } else { cur_root->Balance = BALANCED; reviseBalancefactor = 1; } } else reviseBalancefactor = 0; } else { --size; if (cur_root->left == NULL) { if (cur_root->right == NULL) { delete cur_root; cur_root = NULL; } else { AVLTreeNode* temp = cur_root->right; delete cur_root; cur_root = temp; } reviseBalancefactor = 1; } else { AVLTreeNode* temp = RemoveLastRight(cur_root->left, reviseBalancefactor); cur_root->key = temp->key; cur_root->data = temp->data; delete temp;
if (reviseBalancefactor) { if (cur_root->Balance == LEFTHEAVY) { cur_root->Balance = BALANCED; reviseBalancefactor = 1; } else if (cur_root->Balance == BALANCED) { cur_root->Balance = RIGHTHEAVY; reviseBalancefactor = 0; } else { UpdateRightTree(cur_root, reviseBalancefactor); reviseBalancefactor = !reviseBalancefactor; } } } } }
// Копирование дерева ======================================================================= void AVLTree::CopyNode(AVLTreeNode* &Cur, AVLTreeNode* const &Another) { if (Cur == NULL) Cur = new AVLTreeNode(Another->key, Another->data); else { Cur->key=Another->key; Cur->data=Another->data; }
Cur->Balance = Another->Balance;
if (Another->left != NULL) CopyNode(Cur->left, Another->left); if (Another->right != NULL) CopyNode(Cur->right, Another->right); }
// У заданного дерева отсекает самый правый узел и возвращает указатель на него ============================================ AVLTreeNode* AVLTree::RemoveLastRight(AVLTreeNode* &cur_root, int &reviseBalancefactor) { AVLTreeNode* temp = cur_root; if (cur_root->right == NULL) { if (cur_root->left == NULL) { cur_root = NULL; reviseBalancefactor = 1; return temp; } else { cur_root = temp->left; reviseBalancefactor = 1; return temp; } } else { int rebalanceCurNode; temp = RemoveLastRight(cur_root->right, rebalanceCurNode); if(rebalanceCurNode) { if (cur_root->Balance == RIGHTHEAVY) { cur_root->Balance = BALANCED; reviseBalancefactor = 1; } else if(cur_root->Balance == LEFTHEAVY) UpdateLeftTree(cur_root, reviseBalancefactor); else { cur_root->Balance = LEFTHEAVY; reviseBalancefactor = 0; } } else reviseBalancefactor = 0; return temp; } }
#endif // AVLTREE_HPP
Название: Re: multiple definition of
Отправлено: Fat-Zer от Апреля 28, 2011, 21:19
взял у друга машину машину, вынул двигатель, поставил вместо него лошадь - как машина перестала заводится. Помогите.
По сабжу: все опредаления вынесите из хедера в цпп и будет вам счастье.
Название: Re: multiple definition of
Отправлено: sandurlay от Апреля 28, 2011, 21:24
ок, сделаю.
а все же? что я такого сделал? по сути я убрал только "<T>" и "template<class T>"
Название: Re: multiple definition of
Отправлено: Qt-progger от Мая 28, 2011, 22:43
sandurlay, скинь плз что у тебя получилось по сути я убрал только "<T>" и "template<class T>" с шаблонами
Название: Re: multiple definition of
Отправлено: Qt-progger от Мая 28, 2011, 22:49
я не понял, а где вывод самого дерева то?=/ в Земском я прочитал, что новые классы (создаваемые пользователем) должны наследоваться от кого нибудь и иметь макрос QObject у тебя в коде я этого не заметил че то
Название: Re: multiple definition of
Отправлено: LisandreL от Мая 28, 2011, 23:32
в Земском я прочитал, что новые классы (создаваемые пользователем) должны наследоваться от кого нибудь и иметь макрос QObject Должны... для использования сигналов и слотов, но до этой части фразы в кгнижке вы видимо уже не дочитали. Кроме того макрос правильно пишется Q_OBJECT
|