实验指导
1. 基于二叉链式存储结构实现平衡二叉查找树的典型操作(构造、拷贝构造、析构、赋值运算符重载、节点个数、树高、树宽、增加节点、删除节点、查找一个节点、判空、修改某个节点非关键字部分的数据、先根遍历、后根遍历、中根遍历、按层次遍历),测试和调试程序。
2. 使用平衡二叉查找树完成“树排序”算法,测试和调试程序。“树排序”算法需要使用二叉查找树。我们这里使用平衡二叉查找树完成。完成后运行测试程序检验功能是否正确。
3. 按要求撰写实验报告、录制程序运行以及讲解程序的视频。这一步,要注意管理好时间,认真完成各项任务。在实验网站上对应的实验项目中提交相关文档。按照工程认证的要求,该环节需要锻炼学生自己的口头交流与书面交流的能力。另外注意源程序要缩进正确并有足够的注释,以增强程序可读性。在报告中使用文字以及图表解释清楚自己定义的数据类型、存储结构,并说明这样做的原因;使用文字解释清楚每个函数的设计思路,如果必要的话可以画流程图;对程序进行足够的测试,以检查程序运行是否正确,报告中应全部列出测试数据及其对应的程序运行的屏幕截图。 报告中要包含算法性能的讨论以及根据实现效率在问题的多种解决方案中进行比较、选择的说明。
完整代码
//枚举
enum State_code {
success, fail, range, underflow, overflow, fatal, not_present,
duplicate_error, entry_inserted, entry_found, internal_error
};
enum Balance_factor { left_higher, equal_height, right_higher };
#pragma once
#include "utility.h"
#include <iostream>
/****************************
线性表数组实现
*****************************/
using namespace std;
const int max_list = 10;
template <class List_entry>
class List
{
public:
// methods of the List ADT
List();
int size() const;
bool full() const;
bool empty() const;
void clear();
void traverse(void (*visit)(List_entry&));
State_code retrieve(int position, List_entry& x) const;
State_code replace(int position, const List_entry& x);
State_code remove(int position, List_entry& x);
State_code insert(int position, const List_entry& x);
State_code insert_first(const List_entry& x, List& a_list);
State_code remove_first(List_entry& x, List& a_list);
State_code insert_last(const List_entry& x, List& a_list);
State_code remove_last(List_entry& x, List& a_list);
State_code median_list(List_entry& x, List& a_list);
protected:
// data members for a contiguous list implementation
int count;
List_entry entry[max_list];
};
template <class List_entry>List<List_entry>::List()
{
count = 0;
}
template <class List_entry>int List<List_entry>::size() const
{
return count;
}
template <class List_entry>bool List<List_entry>::full() const
{
return count == max_list;
}
template <class List_entry>bool List<List_entry>::empty() const
{
return count == 0;
}
template <class List_entry>void List<List_entry>::clear()
{
count = 0;
}
template <class List_entry>void List<List_entry>::traverse(void (*visit)(List_entry&))
{
for (int i = 0; i < count; i++)
(*visit)(entry[i]);
}
template <class List_entry>State_code List<List_entry>::retrieve(int position, List_entry& x) const
{
if (position < 0 || position >= count)
return range;
x = entry[position];
return success;
}
template <class List_entry>State_code List<List_entry>::replace(int position, const List_entry& x)
{
if (position < 0 || position >= count)
return range;
entry[position] = x;
return success;
}
template <class List_entry>State_code List<List_entry>::remove(int position, List_entry& x)
{
if (count <= 0)
return underflow;
if (position < 0 || position >= count)
return range;
x = entry[position];
for (int i = position; i < count; i++)
entry[i] = entry[i + 1];
count--;
return success;
}
template <class List_entry>State_code List<List_entry>::insert(int position, const List_entry& x)
{
if (full())
return overflow;
if (position < 0 || position > count)
return range;
for (int i = count - 1; i >= position; i--)
entry[i + 1] = entry[i];
entry[position] = x;
count++;
return success;
}
#pragma once
#pragma once
#include "utility.h"
/****************************
队列数组实现
*****************************/
const int maxqueue = 10;
template<class Queue_entry>
class Queue
{
public:
Queue();
bool empty() const;
State_code serve();
State_code append(const Queue_entry& item);
State_code retrieve(Queue_entry& item)const;
bool full()const;
void clear();
int size()const;
State_code serve_and_retrieve(Queue_entry& item);
int count;
protected:
int front, rear;
Queue_entry entry[maxqueue];
};
//构造函数初始化,队列置为空
template<class Queue_entry>Queue<Queue_entry>::Queue()
{
count = 0;
rear = maxqueue - 1;
front = 0;
}
//队列为空返回true。不为空返回false
template<class Queue_entry>bool Queue<Queue_entry>::empty() const
{
return count == 0;
}
//如果队列不为空,将count-- front向前一格(若向前一格队列满了,则将front置为0)
template<class Queue_entry>State_code Queue<Queue_entry>::serve()
{
if (count <= 0)
return underflow;
count--;
front = ((front + 1) == maxqueue) ? 0 : (front + 1);
return success;
}
//如果队列没有满,将count++ rear向前一格(若超出队列 则将rear置为0)
template<class Queue_entry>State_code Queue<Queue_entry>::append(const Queue_entry& item)
{
if (count >= maxqueue)
return overflow;
count++;
rear = ((rear + 1) == maxqueue) ? 0 : (rear + 1);
entry[rear] = item;
return success;
}
//访问队列首元素
template<class Queue_entry>State_code Queue<Queue_entry>::retrieve(Queue_entry& item)const
{
if (count <= 0)
return underflow;
item = entry[front];
return success;
}
template<class Queue_entry>bool Queue<Queue_entry>::full()const
{
return count == maxqueue;
}
template<class Queue_entry>void Queue<Queue_entry>::clear()
{
count = 0;
front = 0;
rear = maxqueue - 1;
}
template<class Queue_entry>int Queue<Queue_entry>::size()const
{
return count;
}
template<class Queue_entry>State_code Queue<Queue_entry>::serve_and_retrieve(Queue_entry& item)
{
if (count == 0)
return underflow;
else
{
count--;
item = entry[front];
front = ((front + 1) == maxqueue) ? 0 : (front + 1);
return success;
}
}
#pragma
#include"utility.h"
/****************************
栈数组实现
*****************************/
const int maxstack = 10; // small value for testing,符号常量
template<class Stack_entry>
class Stack
{
public:
Stack(); //构造函数,初始化栈
bool empty() const; //判断栈是否为空,const限定为只读,不能修改栈
State_code pop(); //删除(弹出)
State_code top(Stack_entry& item) const; //栈顶操作,const限定为只读,不能修改栈顶元素
State_code push(const Stack_entry& item); //增加(插入)元素,引用节省时间,空间,const限定为只读,不能修改栈中已有元素
private:
int count; //记录栈已有元素数量
Stack_entry entry[maxstack]; //Stack_entry类型待定
};
template<class Stack_entry>Stack<Stack_entry>::Stack()
{
count = 0; //置空栈
}
//若栈满,将outcome置为overflow;否则将item考入entry[]中,并将count++
template<class Stack_entry>State_code Stack<Stack_entry>::push(const Stack_entry& item)
{
State_code outcome = success;
if (count >= maxstack)
{
outcome = overflow; //上溢出
}
else
{
entry[count++] = item; //调用重载运算符
}
return outcome;
}
//如果栈为空,将outcome置为underflow(下溢出);如果栈不为空,将栈顶元素赋值给item
template<class Stack_entry>State_code Stack<Stack_entry>::top(Stack_entry& item) const
{
State_code outcome = success;
if (count == 0)
outcome = underflow;
else
item = entry[count - 1];
return outcome;
}
//栈为空,返回true;不为空,返回false
template<class Stack_entry>bool Stack<Stack_entry>::empty() const
{
bool outcome = true;
if (count > 0) outcome = false;
return outcome;
}
//若栈为空,返回underflow;不为空,覆盖栈顶元素
template<class Stack_entry>State_code Stack<Stack_entry>::pop()
{
State_code outcome = success;
if (count == 0)
outcome = underflow;
else --count;
return outcome;
}
#pragma once
#include <iostream>
using namespace std;
#include "queue.h"
#include "stack.h"
#include "List.h"
/****************************************************************************************************
基于二叉链式存储结构平衡二叉查找树的典型操作
(构造、拷贝构造、析构、赋值运算符重载、节点个数、树高、树宽、增加节点、删除节点、查找一个节点、判空、
修改某个节点非关键字部分的数据、先根遍历、后根遍历、中根遍历、按层次遍历)
*****************************************************************************************************/
template <class Record> struct AVL_node {
// data members:
Record data; //节点数据
AVL_node<Record>* left; //左孩子
AVL_node<Record>* right; //右孩子
Balance_factor balance; //平衡因子
//4 个方法
// constructors:
AVL_node(); //无参构造
AVL_node(const Record& x); //有参构造
void set_balance(Balance_factor b); //建立平衡因子
Balance_factor get_balance() const; //获取平衡因子
};
template <class Record> class AVL_tree {
public:
//17+2 方法数
AVL_tree();
bool empty() const;// 判空
void preorder(void (*visit)(Record&));// 先根遍历
void inorder(void (*visit)(Record&));// 中根遍历
void postorder(void (*visit)(Record&));// 后根遍历
void level_traverse(void (*visit)(Record&));// 按层次遍历
int size() const;// 树中节点总数
int height() const;// 树高
int width() const;// 树宽
void clear();// 置空
AVL_tree(const AVL_tree<Record>& original);// 构造
AVL_tree& operator =(const AVL_tree<Record>& original);// 拷贝构造
~AVL_tree();// 析构
State_code insert(const Record& new_data);// 插入新节点,数据为new_data
State_code remove(const Record& old_data);// 找到数据为old_data 的节点删除
State_code retrieve(Record& target) const;// 查找关键字为target 的节点带回
State_code replace(Record& target);// 查找关键字为target 的节点,修改非关键字部分
// 用于验证树形结构
void print_tree(void (*f)(int indentation, AVL_node<Record>*&));
void prenode(int indentation, AVL_node<Record>* root, void (*f)(int indentation,
AVL_node<Record>*&));
void tree_sort(AVL_tree<Record>&, List<AVL_node<Record>*> &, void (*visit)(Record&));
private:
AVL_node<Record>* root;
};
template <class Record>AVL_node<Record>::AVL_node()
{
data = 0;
left = NULL;
right = NULL;
}
template <class Record>AVL_node<Record>::AVL_node(const Record& x)
{
data = x;
left = right = NULL;
}
template <class Record>void AVL_node<Record>::set_balance(Balance_factor b) //建立平衡因子
{
balance = b;
}
template <class Record>Balance_factor AVL_node<Record>::get_balance() const //获取平衡因子
{
return balance;
}
template <class Record>AVL_tree<Record>::AVL_tree()
{
root = NULL;
}
template <class Record>bool AVL_tree<Record>::empty() const// 判空
{
return root == NULL;
}
template <class Record>void AVL_tree<Record>::preorder(void (*visit)(Record&))// 先根遍历
/*
不是空树,利用栈实现先根遍历。
对于任一节点P,
1)输出节点P,然后将其入栈,再看P的左孩子是否为空;
2)若P的左孩子不为空,则置P的左孩子为当前节点,重复1)的操作;
3)若P的左孩子为空,则将栈顶节点出栈,但不输出,并将出栈节点的右孩子置为当前节点,看其是否为空;
4)若不为空,则循环至1)操作;
5)如果为空,则继续出栈,但不输出,同时将出栈节点的右孩子置为当前节点,看其是否为空,重复4)和5)操作;
6)直到当前节点P为NULL并且栈空,遍历结束。
如果是空树,直接返回。
*/
{
//空树
if (root == NULL)
return;
AVL_node<Record>* p = root;
Stack<AVL_node<Record>* > s;
while (!s.empty() || p)
{
if (p)
{
cout << p->data<<" ";
s.push(p);
p = p->left;
}
else
{
s.top(p);
s.pop();
p = p->right;
}
}
cout << endl;
}
template <class Record>void AVL_tree<Record>::inorder(void (*visit)(Record&))// 中根遍历
/*
* 树不空,利用栈完成中根遍历
对于任一节点P,
1)若P的左孩子不为空,则将P入栈并将P的左孩子置为当前节点,然后再对当前节点进行相同的处理;
2)若P的左孩子为空,则输出P节点,而后将P的右孩子置为当前节点,看其是否为空;
3)若不为空,则重复1)和2)的操作;
4)若为空,则执行出栈操作,输出栈顶节点,并将出栈的节点的右孩子置为当前节点,看起是否为空,重复3)和4)的操作;
5)直到当前节点P为NULL并且栈为空,则遍历结束。
如果是空树,直接返回。
*/
{
if (root == NULL)
return;
//树非空
AVL_node<Record>* p = root;
Stack<AVL_node<Record>* > s;
while (!s.empty() || p)
{
if (p)
{
s.push(p);
p = p->left;
}
else
{
s.top(p);
s.pop();
(*visit)(p->data);
p = p->right;
}
}
}
template <class Record>void AVL_tree<Record>::postorder(void (*visit)(Record&))// 后根遍历
/*
* 树不空,利用栈完成后根遍历
对于任一节点P,
1)先将节点P入栈;
2)若P不存在左孩子和右孩子,或者P存在左孩子或右孩子,但左右孩子已经被输出,则可以直接输出节点P,
并将其出栈,将出栈节点P标记为上一个输出的节点,再将此时的栈顶结点设为当前节点;
3)若不满足2)中的条件,则将P的右孩子和左孩子依次入栈,当前节点重新置为栈顶结点,之后重复操作2);
4)直到栈空,遍历结束。
如果是空树,直接返回。
*/
{
if (root == NULL)
return;
Stack<AVL_node<Record>* > s;
//pCur:当前访问节点,pLastVisit:上次访问节点
AVL_node<Record>* pCur, * pLastVisit;
pCur = root;
pLastVisit = NULL;
//先把pCur移动到左子树最下边
while (pCur)
{
s.push(pCur);
pCur = pCur->left;
}
while (!s.empty())
{
//走到这里,pCur都是空,并已经遍历到左子树底端(看成扩充二叉树,则空,亦是某棵树的左孩子)
s.top(pCur);
s.pop();
//一个根节点被访问的前提是:无右子树或右子树已被访问过
if (pCur->right == NULL || pCur->right == pLastVisit)
{
cout << pCur->data << " ";;
//修改最近被访问的节点
pLastVisit = pCur;
}
//若左子树刚被访问过,则需先进入右子树(根节点需再次入栈)
else
{
//根节点再次入栈
s.push(pCur);
//进入右子树,且可肯定右子树一定不为空
pCur = pCur->right;
while (pCur)
{
s.push(pCur);
pCur = pCur->left;
}
}
}
cout << endl;
}
template <class Record>void AVL_tree<Record>::level_traverse(void (*visit)(Record&))// 按层次遍历
/*
树不空,利用队列完成层次遍历
1)根节点入队
2)循环【查询队首元素放在sub_root,输出sub_root->data,若sub_root->left不空,则入队,若sub_root->right不空,则入队,然后删除队首元素】
3)直到队列为空,循环结束
*/
{
AVL_node<Record>* sub_root;
if (root != NULL)
{
Queue<AVL_node<Record>*> waiting_nodes;
waiting_nodes.append(root);
do
{
waiting_nodes.retrieve(sub_root);
(*visit)(sub_root->data);
if (sub_root->left)
waiting_nodes.append(sub_root->left);
if (sub_root->right)
waiting_nodes.append(sub_root->right);
waiting_nodes.serve();
} while (!waiting_nodes.empty());
}
}
template <class Record>int AVL_tree<Record>::size() const// 树中节点总数
/*
按照层次遍历的思想,每访问一个节点,size++
*/
{
AVL_node<Record>* sub_root;
int size = 0;
if (root != NULL)
{
Queue<AVL_node<Record>*> waiting_nodes;
waiting_nodes.append(root);
do
{
waiting_nodes.retrieve(sub_root);
size++;
if (sub_root->left)
waiting_nodes.append(sub_root->left);
if (sub_root->right)
waiting_nodes.append(sub_root->right);
waiting_nodes.serve();
} while (!waiting_nodes.empty());
}
cout << "节点个数:" << size << endl;
return size;
}
template <class Record>int AVL_tree<Record>::height() const// 树高
/*
* 树不空,利用层次遍历求树高
利用层次遍历非递归求二叉树高度——一层一层地出队列
每次访问完毕一层时,这时队列中存储的刚好是下一层的所有元素
在下一次循环开始时,首先记录该层的元素个数,一次性访问完这一层的所有元素
如果是空树,返回0.
*/
{
/* 判断树是否为空 */
if (!root)
{
return 0;
}
int height = 0; // 初始化树的高度为0
Queue<AVL_node<Record>*> queue; // 初始化一个队列,并将根节点入队
queue.append(root);
/* 当队列不为空时 */
/* 实际上当每次循环开始时,队列中存储的刚好是将要访问下一层的所有元素*/
while (!queue.empty())
{
height++;
int curLevelSize = queue.size(); // 记录当前层元素个数
int cnt = 0;
/* 弹出当前层所有元素 */
while (cnt < curLevelSize)
{
AVL_node<Record>* item;
queue.retrieve(item);
queue.serve();
AVL_node<Record>* temp = item;
//TreeNode* temp = Q.front();
cnt++;
/* 将下一层的元素入队列 */
if (temp->left)
{
queue.append(temp->left);
}
if (temp->right)
{
queue.append(temp->right);
}
}
}
cout << "高度:" << height << endl;
return height;
}
template <class Record>int AVL_tree<Record>::width() const// 树宽
/*
使用二叉树的层次遍历方法,在层次遍历的过程中,通过读取队列中保留的上一层节点数来记录每层的节点数,以获取所有层中最大的节点数。
*/
{
if (root == NULL)
return 0;
int lastLevelWidth = 0;
int CurLevelWidth = 0;
Queue<AVL_node<Record>*> queue;
queue.append(root); //将根节点入队列
int Width = 1; //二叉树的宽度
lastLevelWidth = 1;
AVL_node<Record>* pCur = NULL;
while (!queue.empty())
{
while (lastLevelWidth != 0)
{
AVL_node<Record>* item;
queue.retrieve(item);
pCur = item;
queue.serve();
if (pCur->left) queue.append(pCur->left);
if (pCur->right) queue.append(pCur->right);
lastLevelWidth--;
}
CurLevelWidth = queue.size();
Width = CurLevelWidth > Width ? CurLevelWidth : Width;
lastLevelWidth = CurLevelWidth;
}
cout << "宽度:" << Width << endl;
return Width;
}
template <class Record>void AVL_tree<Record>::clear()// 置空
{
root = NULL;
}
template <class Record>State_code AVL_tree<Record>::insert(const Record& new_data)// 插入新节点,数据为new_data
{
bool taller = true; //是否需要平衡树
AVL_node<Record>* p = root;
AVL_node<Record>* parent = NULL; // 记录前驱结点,方便连接和调整平衡因子
Stack<AVL_node<Record>*> st; //用栈记录插入的路径,方便调整栈中结点的平衡因子;
// 找插入位置,记录路径信息
while (p != NULL) {
if (new_data == p->data)
{ //要插入的数据和AVL树中的数字相同,则返回失败!
return fail;
}
parent = p;
st.push(parent); //找过的入栈
if (new_data < p->data)
{
p = p->left;
}
else if (new_data > p->data)
{
p = p->right;
}
}
p = new AVL_node<Record>(new_data);
p->set_balance(equal_height);
if (parent == NULL)
{
root = p; //判断是不是第一个结点,进行root的连接;
root->set_balance(equal_height);
return success;
}
//此时通过父节点的数据判断插入的是左还是右
if (new_data < parent->data)
{
parent->left = p;
}
else
{
parent->right = p;
}
/// 以上完成插入工作
while (!st.empty())
{ //栈不空,出栈顶元素
st.top(parent);
st.pop();
//插入的是父节点的左孩子
if (p == parent->left)
{
//得到父节点的平衡因子,如果父节点等高,插入之后左高1,不需要平衡树
if (parent->get_balance() == equal_height)
{
parent->set_balance(left_higher);
taller = false;
}
//如果父节点左高,插入之后左高2,需要平衡树
else if (parent->get_balance() == left_higher)
{
parent->set_balance(left_higher);
taller = true;
}
//如果父节点右高,插入之后等高,不需要平衡树
else if (parent->get_balance() == right_higher)
{
parent->set_balance(equal_height);
taller = false;
}
}
//插入的是父节点的右孩子
else if (p == parent->right)
{
//如果父节点等高,插入之后右高1,不需要平衡树
if (parent->get_balance() == equal_height)
{
parent->set_balance(right_higher);
taller = false;
}
//如果父节点左高,插入之后等高,不需要平衡树
else if (parent->get_balance() == left_higher)
{
parent->set_balance(equal_height);
taller = false;
}
//如果父节点右高,插入之后右高2,需要平衡树
else if (parent->get_balance() == right_higher)
{
parent->set_balance(right_higher);
taller = true;
}
}
//以下判断栈中的平衡因子,看是否需要进行旋转调整
if (parent->get_balance() == equal_height)
{ //等高,直接跳出循环
break;
}
//如果taller=false,且父节点右高或左高,代表当前父节点右高1或左高1
if ((!taller)&& ((parent->get_balance() == right_higher) || (parent->get_balance() == left_higher)))
{
p = parent; //此时在向上走,判断平衡因子;
}
//如果taller为真,此时父节点左高2或右高2,需要平衡
else if (taller)
{
if (parent->get_balance() == left_higher) //左高2
{
//LL型,右旋父节点
if ((p->get_balance() == left_higher) && (p == parent->left))
{
AVL_node<Record>* subR = parent;
parent = parent->left;
subR->left = parent->right;
parent->right = subR;
parent->set_balance(equal_height);
subR->set_balance(equal_height);
}
//LR型,先左旋父节点的左孩子,再右旋父节点
else if ((p->get_balance() == right_higher) && (p == parent->left))
{
AVL_node<Record>* subR = parent;
AVL_node<Record>* subL = parent->left;
parent = subL->right;
subL->right = parent->left;
parent->left = subL;
if ((parent->get_balance() == left_higher) || (parent->get_balance() == equal_height))
{
subL->set_balance(equal_height);
}
else
{
subL->set_balance(left_higher);
}
subR->left = parent->right;
parent->right = subR;
if (parent->get_balance() == left_higher)
{
subR->set_balance(right_higher);
}
else
{
subR->set_balance(equal_height);
}
parent->set_balance(equal_height);
}
}
//右高2
else if(parent->get_balance() == right_higher)
{
//RR型,左旋父节点
if ((p->get_balance() == right_higher) && (p == parent->right))
{
AVL_node<Record>* subL = parent;
parent = subL->right;
subL->right = parent->left;
parent->left = subL;
subL->set_balance(equal_height);
parent->set_balance(equal_height);
}
//RL型,先右旋父节点的右孩子,再左旋父节点
else if ((p->get_balance() == left_higher) && (p == parent->right))
{
AVL_node<Record>* subL = parent;
AVL_node<Record>* subR = parent->right;
parent = subR->left;
subR->left = parent->right;
parent->right = subR;
if ((parent->get_balance() == right_higher) || (parent->get_balance() == equal_height))
{
subR->set_balance(equal_height);
}
else
{
subR->set_balance(right_higher);
}
subL->right = parent->left;
parent->left = subL;
if (parent->get_balance() == right_higher)
{
subL->set_balance(left_higher);
}
else
{
subL->set_balance(equal_height);
}
parent->set_balance(equal_height);
}
}
break;
}
}
if (st.empty())
{ //通过旋转函数,此时parent指向根节点;
root = parent; //此时调到栈底了,旋转后将更改root的指向
}
else
{
AVL_node<Record>* tmp;
st.top(tmp); //当前的栈顶结点
if (parent->data < tmp->data)
{
tmp->left = parent;
}
else
{
tmp->right = parent;
}
}
return success;
}
template <class Record>State_code AVL_tree<Record>::remove(const Record& old_data)// 找到数据为old_data 的节点删除
{
bool shorter = true; //树高是否发生变化
Stack< AVL_node<Record>*> st; //用栈记录路径,方便调整栈中结点的平衡因子;
AVL_node<Record>* p = root;
AVL_node<Record>* parent = NULL; //父结点
AVL_node<Record>* q = NULL; //删除结点的辅助结点
AVL_node<Record>* ppr=NULL; //爷爷结点
int flag = 0;
//没有要删除的结点,空树
if (p == NULL)
{
return success;
}
//查找删除点
while (p != NULL)
{
//要删除的数据和AVL树中的数字相同,则跳出,找到了
if (p->data == old_data)
{
break;
}
parent = p;
st.push(parent); //找过的入栈
if (old_data < p->data)
{
p = p->left;
}
else if (old_data > p->data)
{
p = p->right;
}
}
//要删除的节点左右孩子都不空,则在左子树找个最大值替换待删节点
if (p->left != NULL && p->right != NULL)
{
parent = p;
st.push(parent);
//指向左子树,记录在q
q = p->left;
//找到q的右子树为空的节点,此时q为原左子树的最大值
while (q->right != NULL)
{
parent = q;
st.push(parent); //找过的入栈
q = q->right;
}
//替换
p->data = q->data;
p = q;
}
//待删节点的右孩子为空,直接让左孩子替换待删节点
if (p->left != NULL)
{
q = p->left;
}
//待删节点的左孩子为空,直接让右孩子替换待删节点
else
{
q = p->right;
}
//删除的是根结点,并且无入栈,代表树中只有一个节点
if (parent == NULL)
{
root = q;
}
else {
if (parent->left == p)
{
parent->left = q;
}
else
{
parent->right = q;
}
while (!st.empty())
{
st.top(parent);
st.pop();
//在左边删除
if (parent->left == q)
{
//得到父节点的平衡因子,若父节点等高,删除之后右高1,不需要平衡
if (parent->get_balance() == equal_height)
{
parent->set_balance(right_higher);
shorter = false;
}
//得到父节点的平衡因子,若父节点左高,删除之后等高,不需要平衡
else if (parent->get_balance() == left_higher)
{
parent->set_balance(equal_height);
shorter = true;
}
//得到父节点的平衡因子,若父节点右高,删除之后右高2,需要平衡
else if (parent->get_balance() == right_higher)
{
parent->set_balance(right_higher);
shorter = true;
}
}
//在右边删除
else if((parent->right == q))
{
//得到父节点的平衡因子,若父节点等高,删除之后左高1,不需要平衡
if (parent->get_balance() == equal_height)
{
parent->set_balance(left_higher);
shorter = false;
}
//得到父节点的平衡因子,若父节点右高,删除之后等高,不需要平衡
else if (parent->get_balance() == right_higher)
{
parent->set_balance(equal_height);
shorter = true;
}
//得到父节点的平衡因子,若父节点左高,删除之后左高2,需要平衡
else if (parent->get_balance() == left_higher)
{
parent->set_balance(left_higher);
shorter = true;
}
}
//删除前的平衡因子为0,即树高未发生变化,此时不用再调整其它平衡因子,直接退出循环;
if (!shorter)
{
break;
}
//原先左高1\右高1(只有左孩子/右孩子),删除之后等高,树高发生变化
if (shorter&&(parent->get_balance() == equal_height))
{
q = parent; //往上回溯更改爷爷结点的平衡因子;
}
//此时右高2\左高2,已经不平衡了,进行旋转化的调整
else if(shorter)
{
//右高2
if (parent->get_balance() == right_higher)
{
q = parent->right;
//RR型,左旋父节点
if ((q->get_balance() == equal_height)||(q->get_balance() == right_higher))
{
//RotateL(parent);
AVL_node<Record>* subL = parent;
parent = subL->right;
subL->right = parent->left;
parent->left = subL;
subL->set_balance(equal_height);
parent->set_balance(equal_height);
}
//RL型,先右旋父节点的右孩子,再左旋父节点
else if (q->get_balance() == left_higher)
{
AVL_node<Record>* subL = parent;
AVL_node<Record>* subR = parent->right;
parent = subR->left;
subR->left = parent->right;
parent->right = subR;
if ((parent->get_balance() == right_higher) || (parent->get_balance() == equal_height))
{
subR->set_balance(equal_height);
}
else {
subR->set_balance(right_higher);
}
subL->right = parent->left;
parent->left = subL;
if (parent->get_balance() == right_higher) {
subL->set_balance(left_higher);
}
else {
subL->set_balance(equal_height);
}
parent->set_balance(equal_height);
}
}
//左高2
else if (parent->get_balance() == left_higher)
{
q = parent->left;
//LL型,右旋父节点
if ((q->get_balance() == equal_height)|| (q->get_balance() == left_higher))
{
AVL_node<Record>* subR = parent;
parent = parent->left;
subR->left = parent->right;
parent->right = subR;
parent->set_balance(equal_height);
subR->set_balance(equal_height);
}
//LR型,先左旋父节点的左孩子,再右旋父节点
else if (q->get_balance() == right_higher)
{
AVL_node<Record>* subR = parent;
AVL_node<Record>* subL = parent->left;
parent = subL->right;
subL->right = parent->left;
parent->left = subL;
if ((parent->get_balance() == left_higher) || (parent->get_balance() == equal_height))
{
subL->set_balance(equal_height);
}
else {
subL->set_balance(left_higher);
}
subR->left = parent->right;
parent->right = subR;
if (parent->get_balance() == left_higher) {
subR->set_balance(right_higher);
}
else {
subR->set_balance(equal_height);
}
parent->set_balance(equal_height);
}
}
}
}
if (st.empty())
{
root = parent; //直接更改root
}
else
{
AVL_node<Record>* tmp;
st.top(tmp); //当前的栈顶结点使其的左/右指向parent(是旋转化后的根);
if (parent->data < tmp->data)
{
tmp->left = parent;
}
else
{
tmp->right = parent;
}
}
}
delete p; //删除结点;
return success;
}
template <class Record>State_code AVL_tree<Record>::retrieve(Record& target) const// 查找关键字为target 的节点带回
{
//从根开始找,如果target大于sub_root->data,在右边找;如果target小于sub_root->data,在左边找
AVL_node<Record>* sub_root = root;
while (sub_root)
{
if (target == sub_root->data)
{
cout << "节点:"<<sub_root->data << endl;
cout << "左孩子:" << sub_root->left->data << endl;
cout << "右孩子:" << sub_root->right->data << endl;
return success;
}
else if (target > sub_root->data)
sub_root = sub_root->right;
else if (target < sub_root->data)
sub_root = sub_root->left;
}
}
template <class Record>State_code AVL_tree<Record>::replace(Record& target)// 查找关键字为target 的节点,修改非关键字部分
{
//从根开始找,如果target大于sub_root->data,在右边找;如果target小于sub_root->data,在左边找
//找到节点后,修改非关键字部分
AVL_node<Record>* sub_root = root;
while (sub_root)
{
if (target == sub_root->data)
{
sub_root->balance = left_higher;
return success;
}
else if (target > sub_root->data)
sub_root = sub_root->right;
else if (target < sub_root->data)
sub_root = sub_root->left;
}
}
// 用于验证树形结构
template <class Record>void AVL_tree<Record>::print_tree(void (*f)(int indentation, AVL_node<Record>*&))
{
prenode(0, root, f);
}
template <class Record>void AVL_tree<Record>::prenode(int indentation, AVL_node<Record>* root, void (*f)(int indentation,
AVL_node<Record>*&))
{
if (root != NULL)
{
(*f)(indentation, root);
prenode(indentation + 1, root->left, f);
prenode(indentation + 1, root->right, f);
}
}
template <class Record>AVL_tree<Record>::AVL_tree(const AVL_tree<Record>& original)// 构造
{
AVL_node<Record>* sub_root = original.root;
AVL_node<Record>* temp;
if (sub_root == NULL)
temp = NULL;
temp = new AVL_node<Record>(sub_root->data); //构造根
AVL_node<Record>* p = sub_root;
//构造左子树
while (p->left)
{
temp->left = new AVL_node<Record>(p->left->data);
p = p->left;
}
p = sub_root;//指回根
//构造右子树
while (p->right)
{
temp->right = new AVL_node<Record>(p->right->data);
p = p->right;
}
root = sub_root;
}
template <class Record>AVL_tree<Record>& AVL_tree<Record>::operator=(const AVL_tree<Record>& original)// 拷贝构造
{
//复制构造函数,构造出一个对象
AVL_tree<Record> new_copy(original);
clear();
root = new_copy.root;
new_copy.root = NULL;
return *this;
}
//树排序
template <class Record>void AVL_tree<Record>::tree_sort(AVL_tree<Record>& obj , List<AVL_node<Record>*>& c_list, void (*visit)(Record&))
/*
1)将一棵树拷入线性表
2)用线性表中的数据,构造一棵二叉平衡查找树,并清空线性表
3)中根遍历构造的二叉平衡查找树,将遍历结果写入线性表
*/
{
AVL_node<Record>* sub_root;
//将一棵树拷入线性表
if (root != NULL)
{
cout << "排序之前:";
Queue<AVL_node<Record>*> waiting_nodes;
waiting_nodes.append(root);
do
{
waiting_nodes.retrieve(sub_root);
c_list.insert(c_list.size(), sub_root);
cout << sub_root->data << " ";
if (sub_root->left)
waiting_nodes.append(sub_root->left);
if (sub_root->right)
waiting_nodes.append(sub_root->right);
waiting_nodes.serve();
} while (!waiting_nodes.empty());
cout << endl;
}
//用线性表中的数据,构造一棵二叉平衡查找树,并清空线性表
while (!c_list.empty())
{
AVL_node<Record>* item,*temp;
c_list.retrieve(0,item);
c_list.remove(0,temp);
obj.insert(item->data);
}
//中根遍历构造的二叉平衡查找树,将遍历结果写入线性表
if (root == NULL)
return;
//树非空
AVL_node<Record>* p = root;
Stack<AVL_node<Record>* > s;
cout << "排序之后:";
while (!s.empty() || p)
{
if (p)
{
s.push(p);
p = p->left;
}
else
{
s.top(p);
s.pop();
(*visit)(p->data);
c_list.insert(c_list.size(), p);
p = p->right;
}
}
}
template <class Record>AVL_tree<Record>::~AVL_tree()// 析构
{
clear();
}
#include "AVL.h"
#include <iostream>
using namespace std;
#include "List.h"
void write_entry(int& c)
{
cout << c <<" ";
}
void print_node(int indentation, AVL_node<int>*& x) // tree printing function
{
for (int i = 0; i < indentation; i++)
cout << " ";
cout << "( " << x->data << " : -> " << " ";
switch (x->get_balance())
{
case left_higher: cout << "L"; break;
case right_higher: cout << "R"; break;
case equal_height: cout << "E"; break;
}
cout << " ) ===> ";
if (x->left != NULL) cout << (x->left)->data << " ";
if (x->right != NULL) cout << (x->right)->data << " ";
cout << " \n" << flush;
}
char doMenu(void)
{ // Local Declarations
char option;
// Statements
cout << "\n============ Menu =============\n";
cout << " a : Insert new item \n";
cout << " b : Delete a node \n";
cout << " c : Search a node \n";
cout << " d : Update a node \n";
cout << " e : Count the number of nodes \n";
cout << " f : Tree height \n";
cout << " g : Tree width \n";
cout << " h : Pre-order \n";
cout << " i : In-order \n";
cout << " j : Post-order \n";
cout << " k : Level-order \n";
cout << " l : Empty? \n";
cout << " m : Copy constructor \n";
cout << " n : Clear \n";
cout << " o : Print \n";
cout << " q : Quit \n\n";
cout << "=============================== \n";
cout << "Please enter your choice: ";
cin >> option;
option = tolower(option);
return option;
}
// doMenuvoid
int main()
{
AVL_tree<int> obj;
List<AVL_node<int>*> c_list;
int newdata, olddata, target;
while (1)
{
char select = doMenu();
switch (select)
{
case 'a':
cin >> newdata;
obj.insert(newdata); // 插入新节点,数据为new_data
break;
case 'b':
cin >> olddata;
obj.remove(olddata); // 找到数据为old_data 的节点删除
break;
case 'c':
cin >> target;
obj.retrieve(target); // 查找关键字为target 的节点带回
break;
case 'd':
cin >> target;
obj.replace(target); // 查找关键字为target 的节点,修改非关键字部分
break;
case 'e':
obj.size(); // 树中节点总数
break;
case 'f':
obj.height(); // 树高
break;
case 'g':
obj.width(); // 树宽
break;
case 'h':
cout << "先根遍历:" << endl;
obj.preorder(write_entry); // 先根遍历
break;
case 'i':
cout << "中根遍历:" << endl;
obj.inorder(write_entry); // 中根遍历
break;
case 'j':
cout << "后根遍历:" << endl;
obj.postorder(write_entry); // 后根遍历
break;
case 'k':
cout << "按层次遍历:" << endl;
obj.level_traverse(write_entry); //按层次遍历
break;
case 'l':
obj.empty(); //判空
break;
case 'm':
obj.operator=(obj); //赋值运算符重载
break;
case 'n':
obj.clear(); //清空
break;
case 'o': //输出树形结构
obj.print_tree(print_node);
break;
case 'q': //退出系统
return 0;
default: //树排序
obj.tree_sort(obj, c_list, write_entry); //树排序,得到一棵二叉平衡查找树和有序的线性表
cout << endl;
AVL_node<int>* item;
AVL_tree<int> new_obj(obj); //复制构造二叉平衡查找树
new_obj.clear();
while (!c_list.empty())
{
c_list.retrieve(0, item);
c_list.remove(0, item);
new_obj.insert(item->data); //用有序的线性表数据,构造一棵新的二叉平衡查找树
}
new_obj.print_tree(print_node); //输出新二叉平衡查找树的树形结构
}
}
}