I'm working on an AVL Tree sorting algorithm, and I thought I finally had it figured out, thanks to the help of you all, until I realized that the runtime for it was taking significantly longer than the runtime for insertion sort, which shouldn't be correct. I'm using an unsorted array (or rather, vector) of randomly generated numbers. I'll provide some statistics and code below.
AVL
for (std::vector<int>::const_iterator i = numbers.begin(); i != numbers.begin()+30000; ++i)
{
root = insert(root, numbers[x]);
cout << "Height: " << height(root);
x++;
track++;
if( (track % 10000) == 0)
{
cout << track << " iterations" << endl;
time_t now = time(0);
cout << now - begin << " seconds" << endl;
}
}
N = 30,000
Height = 17
Number of iterations performed = ~1,730,000
Run time for sorting = 38 seconds
Insertion Sort
for (int i = 0; i < 30000; i++)
{
first++;
cout << first << " first level iterations" << endl;
time_t now = time(0);
cout << now - begin << " seconds" << endl;
int tmp = dataSet[i];
int j;
for (j = i; i > 0 && tmp < dataSet[j - 1]; j--)
{
dataSet[j] = dataSet[j - 1];
}
dataSet[j] = tmp;
}
}
N = 30,000
Iterations = 30,000
Run time for sorting = 4 seconds
This can't possibly be right, so I was hoping that maybe you all could help figure out what's going on? As far as I can tell, all of my code was implemented correctly, but I'm still going to include the relevant parts below in case I missed something.
Source Code
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;
node* grandChild = child->rightChild;
// perform the rotation
child->rightChild = p;
p->leftChild = grandChild;
// update the height for the nodes
p->height = max(height(p->leftChild), height(p->rightChild)) + 1;
child->height = max(height(child->leftChild), height(child->rightChild)) + 1;
// return new root
return child;
}
node* leftRotate(node* p) // function to left rotate a tree rooted at p
{
node* child = p->rightChild;
node* grandChild = child->leftChild;
// perform the rotation
child->leftChild = p;
p->rightChild = grandChild;
// update heights
p->height = max(height(p->leftChild), height(p->rightChild)) + 1;
// 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*& n, int element)
{
// perform the normal BST insertion
if(n == NULL) // if the tree is empty
return(newNode(element));
if(element< n->data)
{
n->leftChild = insert(n->leftChild, element);
}
else
{
n->rightChild = insert(n->rightChild, element);
}
// update the height for this node
n->height = 1 + max(height(n->leftChild), height(n->rightChild));
// get the balance factor to see if the tree is unbalanced
int balance = getBalance(n);
// the tree is unbalanced, there are 4 different types of rotation to make
// Single Right Rotation (Left Left Case)
if(balance > 1 && element < n->leftChild->data)
{
return rightRotate(n);
}
// Single Left Rotation (Right Right Case)
if(balance < -1 && element > n->rightChild->data)
{
return leftRotate(n);
}
// Left Right Rotation
if(balance > 1 && element > n->leftChild->data)
{
n->leftChild = leftRotate(n->leftChild);
return rightRotate(n);
}
// Right Left Rotation
if(balance < -1 && element < n->rightChild->data)
{
n->rightChild = rightRotate(n->rightChild);
return leftRotate(n);
}
// cout << "Height: " << n->height << endl;
// return the unmodified root pointer in the case that the tree does not become unbalanced
return n;
}