平衡二叉树AVLTree的实现与应用(难度5/10)

news2024/11/16 12:01:05

这是目前难度最高的一个作业,主要难点在于树的平衡,树的平衡依赖于调试输出的图形化,也就是输出二叉树的实现,二叉树的输出技巧性比较强,一般人很难直接想到控制台可以打印二叉树。后面的测试结果显示本文实现的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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/957027.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MYSQL 高级SQL语句

1、按关键字排序&#xff1a; order by 语句用来实现 &#xff0c;前面可以使用where字句使查询结果进一步过滤 asc 是按照升序排序 &#xff0c; 默认的 desc 是按照降序排序 order by的语法结构 例&#xff1a;select name,score from ku order by score desc; 表示将数…

飞书接入ChatGPT,实现智能化问答助手功能,提供高效的解答服务

文章目录 前言环境列表1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 前言 在飞书中创建chatGPT机器人并且对话&#xff0c;在下面操作步骤中…

【源码分析】zeebe actor模型源码解读

zeebe actor 模型&#x1f64b;‍♂️ 如果有阅读过zeebe 源码的朋友一定能够经常看到actor.run() 之类的语法&#xff0c;那么这篇文章就围绕actor.run 方法&#xff0c;说说zeebe actor 的模型。 环境⛅ zeebe release-8.1.14 actor.run() 是怎么开始的&#x1f308; Lon…

APP出海推广前要做哪些事?

一个移动应用APP从开发完成到成功出海&#xff0c;中间要经历哪些过程&#xff1f;上架应用商店、数据对接、各渠道推广要做些什么&#xff1f; 1、上架应用市场 对于想要出海的APP开发商来说&#xff0c;谷歌应用商店Google Play和苹果应用商店Apple APP Store是主要的发行渠…

QT 插件化图像算法研究平台

因工作和生活需要&#xff0c;做了一个插件化的图像算法研究平台。 相关技术如下&#xff1a; 一、插件化 实现了基本的插件框架&#xff0c;能载入插件、加载菜单。 主程序只有插件载入功能。 主窗体、其它任何功能及窗体均由各种插件提供。 二、Opencv相关插件&#xf…

JVM的故事——虚拟机类加载机制

虚拟机类加载机制 文章目录 虚拟机类加载机制一、概述二、类加载的时机三、类加载的过程四、类加载器 一、概述 本章将要讲解class文件如何进入虚拟机以及虚拟机如何处理这些class文件。Java虚拟机把class文件加载到内存&#xff0c;并对数据进行校验、转换解析和初始化&#…

Qt+C++桌面计算器源码

程序示例精选 QtC桌面计算器源码 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<QtC桌面计算器源码>>编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。 学习与…

素数之谜揭秘:一文详解试除法判断素数

这是我非常喜欢的一道编程题目。不要小看这道题&#xff0c;它看似简单&#xff0c;实则奥妙无穷。由于这是C语言的入门篇&#xff0c;只介绍最简单&#xff0c;也最容易想到的方法&#xff1a;试除法。但哪怕是试除法&#xff0c;也有不少变化。 要想了解试除法&#xff0c;首…

Flowable7 设计器

1、flowable7 已经在主版本上移除了Flowable UI相关的包&#xff0c;包含bpm-json相关的所有包和流程设计器相关前端文件。 2、flowable7 版本目前只保留了xml运行相关的包&#xff0c;ui modeler已经移除 3、目前官方给的回复是只能在 flowable 云产品上使用设计器&#xff…

进程的组成:PCB、程序段、数据段

进程的组成:PCB、程序段、数据段 什么是进程 在操作系统中,进程是资源分配和程序执行的基本单位,它是操作系统动态执行的一个程序。 进程是一个动态的概念,当一个程序运行时,它就是一个进程,进程需要相应的系统资源:内存、CPU、文件等等,以保证其能够正确运行。对于同一个程…

短线炒股必杀技

一、短线交易入门基础 1.什么是短线 短线交易博取的是短期差价收益&#xff0c;一般不太关心股票的业绩和潜质&#xff0c;只关心个股近期是否会上涨&#xff0c;具体涨多少。短线投资者以技术派为主&#xff0c;主要依据技术图表进行分析。一般短线投资者的通常持股周期是以几…

设计师都去哪些网站找样机素材

在当今的设计领域&#xff0c;3D样机素材已经成为一个重要的领域。3D样机素材可以让设计师更好地展示他们的设计理念和概念&#xff0c;也可以帮助客户更好地理解设计。为了帮助设计师更容易地创建3D样机素材&#xff0c;以下是我推荐的10个易于使用的3D样机素材网站。 即时设…

那个学C++不没有点大病?一点点癫狂的语法混乱版note和有一点点长的无语的标题,让人怀疑精神状态尼奥

类型转换 切勿混用无符号类型和有符号类型 表达式中两者都有时&#xff0c;有符号类型会转化为无符号类型&#xff0c;当该值为负时会出现非预期结果&#xff1b; unsigned a 1; int b -1; cout<<a*b;//输出 4294967295 //详解: b的源码&#xff1a;100...1 负数转补…

PL端DDR4读写测试实验(未完成)

文章目录 DDR4介绍实验过程编写XDC使用IP核上板验证TODO 参考 DDR4介绍 开发板PL有一颗16bit的DDR4。 先说明硬件信号&#xff08;按该芯片&#xff09;&#xff1a; 信号名说明DQData input/output&#xff0c;双向数据线&#xff08;这个芯片是x16的&#xff0c;使用DQ[15…

SpringBoot初级开发--多环境配置的集成(9)

在Springboot的开发中&#xff0c;我们经常要切换各种各样的环境配置&#xff0c;比如现在是开发环境&#xff0c;然后又切换到生产环境&#xff0c;这个时候用多环境配置就是一个明智的选择。接下来我们沿用上一章的工程来配置多环境配置工程。 1.准备多环境配置文件 这里我…

时序预测 | MATLAB实现基于PSO-GRU、GRU时间序列预测对比

时序预测 | MATLAB实现基于PSO-GRU、GRU时间序列预测对比 目录 时序预测 | MATLAB实现基于PSO-GRU、GRU时间序列预测对比效果一览基本描述程序设计参考资料 效果一览 基本描述 MATLAB实现基于PSO-GRU、GRU时间序列预测对比。 1.MATLAB实现基于PSO-GRU、GRU时间序列预测对比&…

批量剪辑工具:轻松垂直翻转倒立视频画面

你是否曾经遇到这样的情况&#xff1a;拍摄的视频画面是倒立的&#xff0c;但你需要在正立的情况下观看。这时候&#xff0c;你需要一款视频批量剪辑工具来帮助你垂直翻转倒立的视频画面。 首先第一步&#xff0c;我们要打开【视频剪辑高手】&#xff0c;登录账号。 第二步&…

偏置曲柄滑块机构连杆上的双尖点轨迹

偏置曲柄滑块机构是一种常见的机械传动机构&#xff0c;由曲柄、偏置滑块和连杆组成。其中&#xff0c;偏置滑块具有急回特性&#xff0c;可以使机构在运动过程中产生快速的反向运动。 偏置曲柄滑块机构中&#xff0c;连杆上的双尖点轨迹指的是连杆在偏置曲柄滑块机构的运动过…

MOS的减速加速电路设计

引言&#xff1a;在开始讲解MOS的减速加速电路之前&#xff0c;我们还是先来回顾MOS开启与关闭的根本机制。以NMOS为例&#xff0c;开启NMOS本质是对G极进行充电&#xff0c;至Cgs电荷充满&#xff0c;G极才会达到控制端电平值或者开启阈值&#xff0c;关断NMOS时&#xff0c;G…

嵌入式开发之syslog和rsyslog构建日志记录

1.syslogd作客户端 BusyBox v1.20.2 (2022-04-06 16:19:14 CST) multi-call binary.Usage: syslogd [OPTIONS]System logging utility-n Run in foreground-O FILE Log to FILE (default:/var/log/messages)-l N Log only messages more urge…