【发布时间】:2017-04-24 04:57:02
【问题描述】:
所以我最近发布了这个,但我仍然不知道出了什么问题。具体来说,我似乎无法弄清楚是什么导致我的 AVL 树需要这么长时间来排序。我读入一个包含 500,000 个随机、未排序的数字的文件,通过在 for 循环中使用一个向量来一次给树提供一个数字来排序。现在,我还使用普通的 BST 进行了测试,因为有人提到必须一次创建这么多节点可能是为什么它需要这么长时间,但只用了 5 秒就完成了,只跳过了 12,164 个节点。重复。我的 AVL 树需要 3 个小时以上才能对列表的一半进行排序,所以一定是出了问题。谁能弄清楚它是什么?据我所知,重新平衡和插入逻辑是正确的,因为每当我在上面运行一堆测试用例时,它们都很好。我似乎无法找出问题所在。这是我的完整代码,供任何想要查看的人使用。 Main 现在有点乱,因为我包含了所有用于测试目的的东西(比如跟踪循环),但其中大部分将在最终版本中消失。
编辑:
这个问题已经回答了。
#include <iostream>
#include<iomanip>
#include <time.h>
#include <vector>
#include <fstream>
using namespace std;
vector<int> numbers;
struct node
{
public:
int data, height;
node *leftChild, *rightChild;
};
node* root = NULL;
int findMin(node *p) // finds the smallest node in the tree
{
while (p->leftChild != NULL)
p = p->leftChild;
return p->data;
}
int findMax(node *p) // finds the largest node in the tree
{
while(p->rightChild != NULL)
p = p->rightChild;
return p->data;
}
int max(int a, int b) // gets the max of two integers
{
if(a > b)
return a;
else
return b;
}
int height(node *p) // gets the height of the tree
{
if(p == NULL)
return -1;
else
{
p->height = max(height(p->leftChild), height(p->rightChild)) + 1;
}
return p->height;
}
node* newNode(int element) // helper function to return a new node with empty subtrees
{
node* newPtr = new node;
newPtr->data = element;
newPtr->leftChild = NULL;
newPtr->rightChild = NULL;
newPtr->height = 1;
return newPtr;
}
node* rightRotate(node* p) // function to right rotate a tree rooted at p
{
node* child = p->leftChild; // rotate the tree
p->leftChild = child->rightChild;
child->rightChild = p;
// update the height for the nodes
p->height = height(p);
child->height = height(child);
// return new root
return child;
}
node* leftRotate(node* p) // function to left rotate a tree rooted at p
{
node* child = p->rightChild; // perform the rotation
p->rightChild = child->leftChild;
child->leftChild = p;
// update the heights for the nodes
p->height = height(p);
child->height = height(child);
// return new root
return child;
}
int getBalance(node *p)
{
if(p == NULL)
return 0;
else
return height(p->leftChild) - height(p->rightChild);
}
// recursive version of BST insert to insert the element in a sub tree rooted with root
// which returns new root of subtree
node* insert(node*& p, int element)
{
// perform the normal BST insertion
if(p == NULL) // if the tree is empty
return(newNode(element));
if(element < p->data)
{
p->leftChild = insert(p->leftChild, element);
}
else
{
p->rightChild = insert(p->rightChild, element);
}
// update the height for this node
p->height = height(p);
// get the balance factor to see if the tree is unbalanced
int balance = getBalance(p);
// the tree is unbalanced, there are 4 different types of rotation to make
// Single Right Rotation (Left Left Case)
if(balance > 1 && element < p->leftChild->data)
{
return rightRotate(p);
}
// Single Left Rotation (Right Right Case)
if(balance < -1 && element > p->rightChild->data)
{
return leftRotate(p);
}
// Left Right Rotation (double left rotation)
if(balance > 1 && element > p->leftChild->data)
{
p->leftChild = leftRotate(p->leftChild);
return rightRotate(p);
}
// Right Left Rotation
if(balance < -1 && element < p->rightChild->data)
{
p->rightChild = rightRotate(p->rightChild);
return leftRotate(p);
}
// cout << "Height: " << n->height << endl;
// return the unmodified root pointer in the case that the tree does not become unbalanced
return p;
}
void inorder(node *p)
{
if(p != NULL)
{
inorder(p->leftChild);
cout << p->data << ", ";
inorder(p->rightChild);
}
}
void preorder(node *p)
{
if(p != NULL)
{
cout << p->data << ", ";
preorder(p->leftChild);
preorder(p->rightChild);
}
}
void print(node* root)
{
/*cout << "Min Value: " << findMin(root) << endl;
cout << "Max Value: " << findMax(root) << endl;
cout << "Pre Order: ";
preorder(root); */
cout << endl << "Inorder: ";
inorder(root);
cout << endl << endl << endl << endl;
}
void read()
{
int num;
ifstream file_save("data.txt");
if(file_save.is_open())
{
while(!file_save.eof())
{
file_save >> num;
numbers.push_back(num);
}
file_save.close();
}
else
{
cout << "Error in opening file!!" << endl;
}
}
int main()
{
double duration;
time_t begin = time(0);
read();
int x = 0;
int track = 0;
for (std::vector<int>::const_iterator i = numbers.begin(); i != numbers.begin() + 100000; ++i)
{
root = insert(root, numbers[x]);
x++;
track++;
if( (track % 10000) == 0)
{
cout << track << " iterations" << endl;
time_t now = time(0);
cout << now - begin << " seconds" << endl;
}
}
time_t end = time(0);
duration = end - begin;
// print(root);
cout << "The algorithm took " << duration << " seconds to complete." << endl;
return 0;
}
【问题讨论】:
-
你的程序段错误相当快,不知道为什么你认为它需要很长时间才能运行。当您有一个包含 10 个数字的数据文件时,也许创建一个高度为 160 的树与它有关。还有while(eof) is wrong
-
我不确定我是否理解你的意思,你能详细说明一下吗?
-
我试过你的程序。当输入文件有大约 10 个数字时它会崩溃。我还在调试器中运行了它,并观察到它创建的树是无效的。现在启动您自己的调试器并开始调试。
-
我不知道你为什么这么说,因为这些对我来说都不是真的。另外,树怎么无效?小心提供细节,因为我已经调试了好几次,我没有注意到它创建了一个无效的树。
-
this 在您看来是否像一个有效的 AVL 树?对我来说肯定不是。如果您已验证您的 AVL 树是有效的,它是在哪个数据文件上验证的?
标签: c++ algorithm sorting binary-search-tree avl-tree