这是目前难度最高的一个作业,主要难点在于树的平衡,树的平衡依赖于调试输出的图形化,也就是输出二叉树的实现,二叉树的输出技巧性比较强,一般人很难直接想到控制台可以打印二叉树。后面的测试结果显示本文实现的AVLTree 4次战胜std::map。
C++数据结构与算法夯实基础作业列表
平衡部分的调试最好用很少很少量的数据,把各种情况跑一遍,因为一旦不考虑测试集的大小,容易给自己添麻烦。测试集大了之后,调试起来很不方便,哪怕是有输出工具的帮忙。
本作业主要考察:二叉树的平衡、平衡的时机、树的迭代器、模板容器、与二叉搜索树的性能比较
需求如下:
实现一个平衡二叉树
by inserting one record at a time to the tree. It then provides the following menu:
1. Search for a record
2. Insert a record
3. Delete a record
4. List all records
5. Exit
类设计与示例类图:
AVLTree内部直接创建了一个BinarySearchTree,只是多了对BinarySearchTree的再平衡操作;平衡的动作就是AVLTree的成员函数;两种Tree公用TreeNode类型,其中TreeNode的height成员只有AVLTree会使用;两种Tree公用TreeIterator;
部分示例接口与main函数,编程实现代码通过main函数的功能测试:
AVLTree.h
#pragma once
#include "TreeNode.h"
#include "BinarySearchTree.h"
class CAVLTree
{
public:
CAVLTree(){}
bool Empty(void) const { return m_root.Empty(); }
bool Exists(const int _key) const;
void Clear(void);
//The reason of using this version of Delete see the annotation of member function DeletePri
void Delete(CTreeIterator _itr);
virtual void Insert(const int _key, const CEntry& _value);
friend ostream& operator<<(ostream& _os, const CBinarySearchTree& tree);
void Print(ostream& _os) const;
void print_in_order(void) const;
CTreeIterator Find(const int key);
CTreeIterator Begin() { return m_root.min(); }
CTreeIterator End(void) { return CTreeIterator(nullptr); }
private:
void InsertPri(CTreeNode*& _pNode, CTreeNode*& _pParentNode, const int _key, const CEntry& _entry);
//Not use this member function "DeletePri" , because the balance of AVLTree is a time-consuming job.
//See that the member function InsertPri always balance the tree recursive, so we can use it to do the balance job.
void DeletePri(CTreeNode* &node, const CEntry& _entry);
void LeftLeftRotate(CTreeNode* &k2);
void RightRightRotate(CTreeNode* &k2);
void DoubleRotateLR(CTreeNode* &k3);
void DoubleRotateRL(CTreeNode* &k3);
private:
CBinarySearchTree m_root;
};
BinarySearchTree.h
#ifndef _BINARY_TREE_H_
#define _BINARY_TREE_H_
#include <cassert>
#include <iostream>
#include <stack>
#include <string>
using namespace std;
#include "TreeNode.h"
#include "TreeIterator.h"
class CAVLTree;
class CBinarySearchTree
{
friend CAVLTree;
public:
CBinarySearchTree() :m_root(NULL) { }
~CBinarySearchTree(void) { Clear(); }
virtual void Insert(const int _key, const CEntry& _value);
bool Empty(void) const { return (NULL == m_root); }
bool Exists(const int key) const;
void Clear(void);
virtual void Delete(const int key);
virtual void Delete(CTreeIterator _itr);//for overwrite, for example AVLTree will overwrite
friend ostream& operator<<(ostream& out, const CBinarySearchTree& tree);
void Print(ostream& out) const;
void print_in_order(void) const;
CTreeIterator Find(const int key);
CTreeIterator Begin() { return min(); }
CTreeIterator End(void) { return CTreeIterator(nullptr); }
CTreeIterator min(void);
CTreeIterator getRoot(void);
protected:
void print_binary_tree(ostream&, const CTreeNode* bt, int depth) const;
//delete the node has only one child at most
void eraseTheOnlyOneChild(CTreeNode* _pNode);
void eraseRoot(CTreeNode* _pNode);
private:
CBinarySearchTree(const CBinarySearchTree&) = delete;
CBinarySearchTree& operator = (const CBinarySearchTree&) = delete;
private:
CTreeNode* m_root;
};
#endif
Entry.h
#pragma once
#include<string>
using namespace std;
class CEntry
{
public:
CEntry();
CEntry(const int _code, int _population, const string& _name);
~CEntry();
friend ostream& operator<< (ostream& _os, const CEntry& _entry);
friend istream& operator>> (istream& _is, CEntry& _entry);
friend bool operator > (const CEntry& _lhs, const CEntry& _rhs);
friend bool operator >= (const CEntry& _lhs, const CEntry& _rhs);
friend bool operator < (const CEntry& _lhs, const CEntry& _rhs);
friend bool operator <= (const CEntry& _lhs, const CEntry& _rhs);
friend bool operator == (const CEntry& _lhs, const CEntry& _rhs);
int GetCode(void) const;
void SetCode(const int _code) { m_code = _code; }
private:
int m_code;
int m_population;
string m_name;
};
Timer.h
#pragma once
#include <ctime>
#include <limits>
using namespace std;
class CTimer
{
public:
CTimer() { _start_time = std::clock(); }
void restart() { _start_time = std::clock(); }
double elapsed() const
{
return double(std::clock() - _start_time)/* / CLOCKS_PER_SEC*/;
}
double elapsed_max() const
{
return (double((std::numeric_limits<std::clock_t>::max)())
- double(_start_time))/* / double(CLOCKS_PER_SEC)*/;
}
double elapsed_min() const
{
return double(1) /*/ double(CLOCKS_PER_SEC)*/;
}
private:
std::clock_t _start_time;
};
TreeIterator.h
#pragma once
class CTreeNode;
class CAVLTree;
//CTreeIterator
class CTreeIterator
{
public:
friend class CBinarySearchTree;
friend class CAVLTree;
CTreeIterator(void) :m_pNode(nullptr){}
CTreeIterator(CTreeNode* _pNode) :m_pNode(_pNode) {};
bool equalTo(const CTreeIterator& rhs) { return m_pNode == rhs.m_pNode; }
CTreeNode* operator->(void) { return m_pNode; }
CTreeNode* get(void) { return m_pNode; }
CTreeIterator& operator++(void);//++itr
bool operator==(CTreeIterator& _rhs) { return this->m_pNode == _rhs.get(); }
bool operator!=(CTreeIterator& _rhs) { return !(this->m_pNode == _rhs.get()); }
private://user can not use raw pointer
static CTreeNode* successor(CTreeNode* _pNode);
static CTreeNode* min(CTreeNode* _pNode);
private:
CTreeNode* m_pNode;
};
TreeNode.h
#pragma once
#include <string>
using namespace std;
#include "Entry.h"
//this node for both BST and AVLTree
class CTreeNode
{
public:
CTreeNode() :key(int()), height(1), parent(nullptr), lchild(nullptr), rchild(nullptr) {}
CTreeNode(const int t) :key(t), height(1), parent(nullptr), lchild(nullptr), rchild(nullptr) {}
CTreeNode(const int t, const CEntry& _value) :key(t), height(1), value(_value), parent(nullptr), lchild(nullptr), rchild(nullptr) {}
static bool IsLchild(const CTreeNode* _pParent, const CTreeNode* _pNode);
static bool IsRchild(const CTreeNode* _pParent, const CTreeNode* _pNode);
static bool isNodeHasTwoChild(const CTreeNode* _pNode);
static int GetHeight(const CTreeNode* _pNode);
static void UpdateParentHeight(CTreeNode* _pNode);
private:
//CTreeNode(const CTreeNode&) = delete;
//CTreeNode& operator=(const CTreeNode&) = delete;
public:
int key;
int height;//just for AVLTree to avoid recursive height function call
CEntry value;
CTreeNode* parent;
CTreeNode* lchild;
CTreeNode* rchild;
};
main.cpp
#include <iostream>
#include <chrono>
#include <fstream>
#include <iterator>
#include <iomanip>
#include <list>
#include <random>
using namespace std;
#include "AVLTree.h"
#include "BinarySearchTree.h"
#include "Counter.h"
#include "CounterType.h"
#include "Timer.h"
void LoadData(const string& _fileName, list<CEntry>& _entryList)
{
ifstream fin(_fileName);
istream_iterator<CEntry> itrBegin(fin), itrEnd;
copy(itrBegin, itrEnd, back_inserter(_entryList));
}
void Compare(int scaleNumber, ostream& _os, const std::list<int>& _fromData)
{
CBinarySearchTree bst;
CAVLTree avlTree;
CEntry entry;
CTimer timer;
const std::list<int>& listInteger = _fromData;
///compare insert///
timer.restart();
//Counter::Reset(CounterType::AVLInsert);
for (auto itr = listInteger.begin(); itr != listInteger.end(); itr++)
{
entry.SetCode(*itr);
avlTree.Insert(*itr, entry);
}
auto elapsed = timer.elapsed();
cout << "Insert " << scaleNumber << " times to AVLTree cost " << elapsed << " milliseconds, " << endl; //Counter::GetCount(CounterType::AVLInsert) << " nodes has been traversed" << endl;
_os << "Insert " << scaleNumber << " times to AVLTree cost " << elapsed << " milliseconds, " << endl; //Counter::GetCount(CounterType::AVLInsert) << " nodes has been traversed" << endl;
//avlTree.Print(cout);
timer.restart();
//Counter::Reset(CounterType::BSTInsert);
for (auto itr = listInteger.begin(); itr != listInteger.end(); itr++)
{
entry.SetCode(*itr);
bst.Insert(*itr, entry);
}
elapsed = timer.elapsed();
cout << "Insert " << scaleNumber << " times to BST cost " << elapsed << " milliseconds, " << endl; //Counter::GetCount(CounterType::BSTInsert) << " nodes has been traversed" << endl;
_os << "Insert " << scaleNumber << " times to BST cost " << elapsed << " milliseconds, " << endl; //Counter::GetCount(CounterType::BSTInsert) << " nodes has been traversed" << endl;
//bst.Print(cout);
//compare search
timer.restart();
//Counter::Reset(CounterType::BSTFind);
for (auto itr = listInteger.begin(); itr != listInteger.end(); itr++)
{
auto itrFind = avlTree.Find(*itr);
assert(itrFind != avlTree.End());
}
elapsed = timer.elapsed();
cout << "Search " << scaleNumber << " times from AVLTree cost " << elapsed << " milliseconds, " << endl; //Counter::GetCount(CounterType::BSTFind) << " nodes has been traversed" << endl;
_os << "Search " << scaleNumber << " times from AVLTree cost " << elapsed << " milliseconds, " << endl; //Counter::GetCount(CounterType::BSTFind) << " nodes has been traversed" << endl;
timer.restart();
//Counter::Reset(CounterType::BSTFind);
for (auto itr = listInteger.begin(); itr != listInteger.end(); itr++)
{
auto itrFind = bst.Find(*itr);
assert(itrFind != bst.End());
}
elapsed = timer.elapsed();
cout << "Search " << scaleNumber << " times from BST cost " << elapsed << " milliseconds, " << endl; //Counter::GetCount(CounterType::BSTFind) << " nodes has been traversed" << endl;
_os << "Search " << scaleNumber << " times from BST cost " << elapsed << " milliseconds, " << endl; //Counter::GetCount(CounterType::BSTFind) << " nodes has been traversed" << endl;
///compare delete///
timer.restart();
//Counter::Reset(CounterType::AVLDelete);
for (auto itr = listInteger.begin(); itr != listInteger.end(); itr++)
{
auto itrFind = avlTree.Find(*itr);
if (itrFind != avlTree.End())
{
avlTree.Delete(itrFind);
}
}
elapsed = timer.elapsed();
cout << "Delete " << scaleNumber << " times from AVLTree cost " << elapsed << " milliseconds, " << endl; //Counter::GetCount(CounterType::AVLDelete) << " nodes has been traversed" << endl;
_os << "Delete " << scaleNumber << " times from AVLTree cost " << elapsed << " milliseconds, " << endl; //Counter::GetCount(CounterType::AVLDelete) << " nodes has been traversed" << endl;
timer.restart();
//Counter::Reset(CounterType::BSTDelete);
for (auto itr = listInteger.begin(); itr != listInteger.end(); itr++)
{
auto itrFind = bst.Find(*itr);
if (itrFind != bst.End())
{
bst.Delete(itrFind);
}
}
elapsed = timer.elapsed();
cout << "Delete " << scaleNumber << " times from BST cost " << elapsed << " milliseconds, " << endl; //Counter::GetCount(CounterType::BSTDelete) << " nodes has been traversed" << endl;
_os << "Delete " << scaleNumber << " times from BST cost " << elapsed << " milliseconds, " << endl; //Counter::GetCount(CounterType::BSTDelete) << " nodes has been traversed" << endl;
}
void CompareBSTAndAVLTWithRandomData(int scaleNumber, ostream& _os)
{
cout << "CompareBSTAndAVLTWithRandomData:" << endl;
_os << "CompareBSTAndAVLTWithRandomData:" << endl;
CBinarySearchTree bst;
CAVLTree avlTree;
CTimer timer;
unsigned seed1 = std::chrono::system_clock::now().time_since_epoch().count();
std::mt19937 g1(seed1); // mt19937 is a standard mersenne_twister_engine
list<int> listInteger;
for (int i = 0; i < scaleNumber; ++i)
{
int number = g1();
listInteger.push_back(number);
}
_os << endl;
CEntry entry;
int key;
Compare(scaleNumber, _os, listInteger);
}
void CompareBSTAndAVLTWithSortedData(int scaleNumber, ostream& _os)
{
cout << "CompareBSTAndAVLTWithSortedData:" << endl;
_os << "CompareBSTAndAVLTWithSortedData:" << endl;
unsigned seed1 = std::chrono::system_clock::now().time_since_epoch().count();
std::mt19937 g1(seed1); // mt19937 is a standard mersenne_twister_engine
list<int> listInteger;
for (int i = 0; i < scaleNumber; ++i)
{
listInteger.push_back(i);
}
Compare(scaleNumber, _os, listInteger);
}
int main()
{
cout << "Author: (modified)\n";
//CBinarySearchTree tree;
CAVLTree tree;
list<CEntry> entryList;
LoadData("p4large.txt", entryList);
//LoadData("p4largeSorted.txt", entryList);
//LoadData("p4small.txt", entryList);
int i = 0;
for (auto& iRef : entryList)
{
//Insert a record
++i;
//tree.Print(cout);
//cout << "load :" << i << " " << iRef.GetCode() << endl;
tree.Insert(iRef.GetCode(), iRef);
}
CTimer timer;
while (true)
{
int menu;
cout << "Please input menu:" << endl;
cout << "0 : Draw the tree." << endl;
cout << "1 : Search a record." << endl;
cout << "2 : Insert a record." << endl;
cout << "3 : Delete a record." << endl;
cout << "4 : List all reacords." << endl;
cout << "5 : Exit." << endl;
cout << "6 : Compare AVLT with BST use [insert/ find/ delete]." << endl;
cin >> menu;
switch (menu)
{
case 0:
tree.Print(cout);
break;
case 1:
{
//Search a record
cout << "Please input the code of the state:" << endl;
int code;
cin >> code;
timer.restart();
auto pNode = tree.Find(code);
auto elasped = timer.elapsed();
if (pNode == tree.End())
{
cout << "not Find " << code << endl;
cout << "time elasped:"<<elasped << endl;
}
else
{
cout << "Find : " << pNode->value << endl;
cout << "time elasped:" << elasped << endl;
}
break;
}
case 2:
{
//Insert a record
cout << "Insert a record be exactly alike the format :code,population,\"statename\"" << endl;
cout << "For example you can input(never forgot the comma and semicolon):06055,225,\"Napa, CA\"" << endl;
CEntry entry;
cin.ignore();
cin >> entry;
auto pNode = tree.Find(entry.GetCode());
if (pNode == tree.End())
{
timer.restart();
tree.Insert(entry.GetCode(), entry);
auto elasped = timer.elapsed();
cout << "Insert record successed." << endl;
cout << "time elasped:" << elasped << endl;
}
else
{
cout << "Can not Insert the record, because same code already in the tree!" << endl;
}
break;
}
case 3:
{
cout << "Input the code of state you want to delete:" << endl;
int code;
cin >> code;
auto itr = tree.Find(code);
if (itr == tree.End())
{
cout << "not Find " << code << endl;
}
else
{
cout << "Find : " << itr->value << endl;
timer.restart();
tree.Delete(itr);
auto elasped = timer.elapsed();
cout << setfill('0') << setw(5) << code << " is deleted." << endl;
cout << "time elasped:" << elasped << endl;
}
break;
}
case 4:
{
cout << "List all records( see also in file ListAllRecordsData.txt):" << endl;
CTreeIterator itr = tree.Begin();
ofstream fout("ListAllRecordsData.txt");//Temp project write data to file.
while (!itr.equalTo(tree.End()))
{
cout << itr->value << endl;
fout << itr->value << endl;// List all records to a text file
++itr;
}
break;
}
case 5:
cout << "System Exit." << endl;
return 0;
case 6:
{
cout << "Please input the scale number for test:";
int scaleNumber;
cin >> scaleNumber;
ofstream fout("CompareResultBetweenAVLTAndBST.txt");
CompareBSTAndAVLTWithSortedData(scaleNumber, fout);
CompareBSTAndAVLTWithRandomData(scaleNumber, fout);
cout << "The compare result have written to compare.txt" << endl;
}
break;
default:
cout << "Error Input!" << endl;
break;
}
}
return 0;
}
功能与输出:
Please input menu:
0 : Draw the tree.
1 : Search a record.
2 : Insert a record.
3 : Delete a record.
4 : List all reacords.
5 : Exit.
6 : Compare AVLT with BST use [insert/ find/ delete].
0
The tree is(in-order):
---(06115, 105, "Yuba, CA")
---(06113, 438, "Yolo, CA")
---(06111, 1130, "Ventura, CA")
---(06109, 3, "Tuolumne, CA")
---(06107, 577, "Tulare, CA")
---(06105, 0, "Trinity, CA")
---(06103, 25, "Tehama, CA")
---(06101, 172, "Sutter, CA")
---(06099, 576, "Stanislaus, CA")
---(06097, 655, "Sonoma, CA")
---(06095, 570, "Solano, CA")
---(06093, 4, "Siskiyou, CA")
---(06091, 0, "Sierra, CA")
---(06089, 29, "Shasta, CA")
---(06087, 373, "Santa Cruz, CA")
---(06085, 5889, "Santa Clara, CA")
---(06083, 721, "Santa Barbara, CA")
---(06081, 1743, "San Mateo, CA")
---(06079, 171, "San Luis Obispo, CA")
---(06077, 795, "San Joaquin, CA")
---(06075, 2039, "San Francisco, CA")
---(06073, 5351, "San Diego, CA")
---(06071, 1920, "San Bernardino, CA")
---(06069, 94, "San Benito, CA")
---(06067, 1809, "Sacramento, CA")
---(06065, 1784, "Riverside, CA")
---(06063, 0, "Plumas, CA")
---(06061, 162, "Placer, CA")
---(06059, 6214, "Orange, CA")
---(06057, 26, "Nevada, CA")
---(06055, 225, "Napa, CA")
---(06053, 1122, "Monterey, CA")
---(06051, 19, "Mono, CA")
06049, 0, "Modoc, CA"
---(06047, 341, "Merced, CA")
---(06045, 102, "Mendocino, CA")
---(06043, 1, "Mariposa, CA")
---(06041, 399, "Marin, CA")
---(06039, 221, "Madera, CA")
---(06037, 22851, "Los Angeles, CA")
---(06035, 1, "Lassen, CA")
---(06033, 32, "Lake, CA")
---(06031, 205, "Kings, CA")
---(06029, 875, "Kern, CA")
---(06027, 8, "Inyo, CA")
---(06025, 295, "Imperial, CA")
---(06023, 42, "Humboldt, CA")
---(06021, 36, "Glenn, CA")
---(06019, 1242, "Fresno, CA")
---(06017, 90, "El Dorado, CA")
---(06015, 19, "Del Norte, CA")
---(06013, 1372, "Contra Costa, CA")
---(06011, 60, "Colusa, CA")
---(06009, 1, "Calaveras, CA")
---(06007, 150, "Butte, CA")
---(06005, 1, "Amador, CA")
---(06003, 0, "Alpine, CA")
---(06001, 3648, "Alameda, CA")
Please input menu:
0 : Draw the tree.
1 : Search a record.
2 : Insert a record.
3 : Delete a record.
4 : List all reacords.
5 : Exit.
6 : Compare AVLT with BST use [insert/ find/ delete].
1
Please input the code of the state:
06105
Find : 06105, 0, "Trinity, CA"
time elasped:0
Please input menu:
0 : Draw the tree.
1 : Search a record.
2 : Insert a record.
3 : Delete a record.
4 : List all reacords.
5 : Exit.
6 : Compare AVLT with BST use [insert/ find/ delete].
6
Please input the scale number for test:100000
CompareBSTAndAVLTWithSortedData:
Insert 100000 times to AVLTree cost 30 milliseconds,
Insert 100000 times to std::map cost 19 milliseconds,
Insert 100000 times to BST cost 27367 milliseconds,
Search 100000 times from AVLTree cost 5 milliseconds,
Search 100000 times from std::map cost 9 milliseconds,
Search 100000 times from BST cost 26900 milliseconds,
Delete 100000 times from AVLTree cost 7 milliseconds,
Delete 100000 times from std::map cost 8 milliseconds,
Delete 100000 times from BST cost 6 milliseconds,
CompareBSTAndAVLTWithRandomData:
Insert 100000 times to AVLTree cost 49 milliseconds,
Insert 100000 times to std::map cost 42 milliseconds,
Insert 100000 times to BST cost 33 milliseconds,
Search 100000 times from AVLTree cost 24 milliseconds,
Search 100000 times from std::map cost 30 milliseconds,
Search 100000 times from BST cost 24 milliseconds,
Delete 100000 times from AVLTree cost 30 milliseconds,
Delete 100000 times from std::map cost 37 milliseconds,
Delete 100000 times from BST cost 32 milliseconds,
The compare result have written to compare.txt
Please input menu:
0 : Draw the tree.
1 : Search a record.
2 : Insert a record.
3 : Delete a record.
4 : List all reacords.
5 : Exit.
6 : Compare AVLT with BST use [insert/ find/ delete].
0
The tree is(in-order):
---(06115, 105, "Yuba, CA")
---(06113, 438, "Yolo, CA")
---(06111, 1130, "Ventura, CA")
---(06109, 3, "Tuolumne, CA")
---(06107, 577, "Tulare, CA")
---(06105, 0, "Trinity, CA")
---(06103, 25, "Tehama, CA")
---(06101, 172, "Sutter, CA")
---(06099, 576, "Stanislaus, CA")
---(06097, 655, "Sonoma, CA")
---(06095, 570, "Solano, CA")
---(06093, 4, "Siskiyou, CA")
---(06091, 0, "Sierra, CA")
---(06089, 29, "Shasta, CA")
---(06087, 373, "Santa Cruz, CA")
---(06085, 5889, "Santa Clara, CA")
---(06083, 721, "Santa Barbara, CA")
---(06081, 1743, "San Mateo, CA")
---(06079, 171, "San Luis Obispo, CA")
---(06077, 795, "San Joaquin, CA")
---(06075, 2039, "San Francisco, CA")
---(06073, 5351, "San Diego, CA")
---(06071, 1920, "San Bernardino, CA")
---(06069, 94, "San Benito, CA")
---(06067, 1809, "Sacramento, CA")
---(06065, 1784, "Riverside, CA")
---(06063, 0, "Plumas, CA")
---(06061, 162, "Placer, CA")
---(06059, 6214, "Orange, CA")
---(06057, 26, "Nevada, CA")
---(06055, 225, "Napa, CA")
---(06053, 1122, "Monterey, CA")
---(06051, 19, "Mono, CA")
06049, 0, "Modoc, CA"
---(06047, 341, "Merced, CA")
---(06045, 102, "Mendocino, CA")
---(06043, 1, "Mariposa, CA")
---(06041, 399, "Marin, CA")
---(06039, 221, "Madera, CA")
---(06037, 22851, "Los Angeles, CA")
---(06035, 1, "Lassen, CA")
---(06033, 32, "Lake, CA")
---(06031, 205, "Kings, CA")
---(06029, 875, "Kern, CA")
---(06027, 8, "Inyo, CA")
---(06025, 295, "Imperial, CA")
---(06023, 42, "Humboldt, CA")
---(06021, 36, "Glenn, CA")
---(06019, 1242, "Fresno, CA")
---(06017, 90, "El Dorado, CA")
---(06015, 19, "Del Norte, CA")
---(06013, 1372, "Contra Costa, CA")
---(06011, 60, "Colusa, CA")
---(06009, 1, "Calaveras, CA")
---(06007, 150, "Butte, CA")
---(06005, 1, "Amador, CA")
---(06003, 0, "Alpine, CA")
---(06001, 3648, "Alameda, CA")
Please input menu:
0 : Draw the tree.
1 : Search a record.
2 : Insert a record.
3 : Delete a record.
4 : List all reacords.
5 : Exit.
6 : Compare AVLT with BST use [insert/ find/ delete].
4
List all records( see also in file ListAllRecordsData.txt):
06001, 3648, "Alameda, CA"
06003, 0, "Alpine, CA"
06005, 1, "Amador, CA"
06007, 150, "Butte, CA"
06009, 1, "Calaveras, CA"
06011, 60, "Colusa, CA"
06013, 1372, "Contra Costa, CA"
06015, 19, "Del Norte, CA"
06017, 90, "El Dorado, CA"
06019, 1242, "Fresno, CA"
06021, 36, "Glenn, CA"
06023, 42, "Humboldt, CA"
06025, 295, "Imperial, CA"
06027, 8, "Inyo, CA"
06029, 875, "Kern, CA"
06031, 205, "Kings, CA"
06033, 32, "Lake, CA"
06035, 1, "Lassen, CA"
06037, 22851, "Los Angeles, CA"
06039, 221, "Madera, CA"
06041, 399, "Marin, CA"
06043, 1, "Mariposa, CA"
06045, 102, "Mendocino, CA"
06047, 341, "Merced, CA"
06049, 0, "Modoc, CA"
06051, 19, "Mono, CA"
06053, 1122, "Monterey, CA"
06055, 225, "Napa, CA"
06057, 26, "Nevada, CA"
06059, 6214, "Orange, CA"
06061, 162, "Placer, CA"
06063, 0, "Plumas, CA"
06065, 1784, "Riverside, CA"
06067, 1809, "Sacramento, CA"
06069, 94, "San Benito, CA"
06071, 1920, "San Bernardino, CA"
06073, 5351, "San Diego, CA"
06075, 2039, "San Francisco, CA"
06077, 795, "San Joaquin, CA"
06079, 171, "San Luis Obispo, CA"
06081, 1743, "San Mateo, CA"
06083, 721, "Santa Barbara, CA"
06085, 5889, "Santa Clara, CA"
06087, 373, "Santa Cruz, CA"
06089, 29, "Shasta, CA"
06091, 0, "Sierra, CA"
06093, 4, "Siskiyou, CA"
06095, 570, "Solano, CA"
06097, 655, "Sonoma, CA"
06099, 576, "Stanislaus, CA"
06101, 172, "Sutter, CA"
06103, 25, "Tehama, CA"
06105, 0, "Trinity, CA"
06107, 577, "Tulare, CA"
06109, 3, "Tuolumne, CA"
06111, 1130, "Ventura, CA"
06113, 438, "Yolo, CA"
06115, 105, "Yuba, CA"
Please input menu:
0 : Draw the tree.
1 : Search a record.
2 : Insert a record.
3 : Delete a record.
4 : List all reacords.
5 : Exit.
6 : Compare AVLT with BST use [insert/ find/ delete].
测试结果说明:
1 可以看出二叉搜索树在插入排序数据后退化为单链表,在Insert和Search的时候耗时非常高。平衡二叉树不存在这个问题,对于排序数据和随机数据都一样支持的很好。
2 从测试结果可以看出AVLTree整体上和std::map一个水平,四次用时超越std::map