#include<iostream>
#include<stdio.h>
#include<stack>
#include<queue>
#include<malloc.h>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<opencv.hpp>
using namespace cv;
using namespace std;
//struct area
typedef struct node {
int data;
int short bal;
struct node *left_child;
struct node *right_child;
struct node *parent;
}BST;
typedef struct {
int x;
int y;
}POS;
//universal variance area
int Mapsequence[60] = { 0 };
int countMap = 1;
POS pos;
BST *ROOT=NULL;//平衡二叉树的根节点
//function announce
BST *SortTreeCreate();
BST *SortTreeSearch(BST *root, int key);
void Levelorder(BST *Tree);
void mapping(BST *T);
void Posfunction(int num);
void drawnode(int b, int g, int r);
void RotateRL(BST *parent, BST *T);
int Height(BST *T);
void Calbalance(BST *T);
void RotateRight(BST *parent, BST *T);
void RotateLR(BST *parent, BST *T);
void RotateLeft(BST *parent, BST *T);
void InsertBalance(BST *x, BST *T);
void RotateRL(BST *parent, BST *T);
void Insert(int data);
//function announce
Mat image(1000, 1000, CV_8UC3);
int main()
{
namedWindow("tree");
int key, i = 1; BST *p = NULL;
printf("Please enter the key you want to search:");
scanf("%d", &key);
SortTreeCreate();//创建平衡二叉树查找树
mapping(ROOT);//给二叉树查找树中的每个节点编号
drawnode(0, 255, 0);//用绿色画节点
p = SortTreeSearch(ROOT, key);
if (p)//判断需要查找的节点是否存在
{
printf("The key:%d is exisiting!\n", p->data);
while (Mapsequence[i++] != 0)
{
if (Mapsequence[i - 1] == p->data)break;
}
Posfunction(i - 1);
circle(image, Point(pos.x, pos.y), 25, Scalar(0, 0, 255), -1);
imshow("tree", image);
waitKey(0);
}
else
printf("No this key in Binary Search Tree!\n");
}
//function area
BST *SortTreeCreate()
{
int data, n = 0, i = 0, runone = 1;
FILE *fp;
BST *p;
if (!(fp = fopen("C:\\Users\\chenh\\Desktop\\新建文件夹 (3)\\DATA.txt", "r")))
{
printf("Open the file error!\n");
exit(1);
}
//This while is to read the data data file and creat Binary Search Tree
while (!feof(fp))
{
fscanf(fp, "%d\n", &data);
Insert(data);
}
return ROOT;
}
BST *SortTreeSearch(BST *root, int key)
{
if (!root) return NULL;//if root is null
if (key == root->data) return root;
if (key < root->data)
return SortTreeSearch(root->left_child, key);
return SortTreeSearch(root->right_child, key);
}
void mapping(BST *T)
//This function is to mapping node map
//这个函数的作用是将树节点的序号映射到一个数组中(编号)
{
Levelorder(T);
}
void Levelorder(BST *Tree) //层序遍历_队列实现
{
//利用了一点点C++的东西 稍微看一下就知道了,给该二叉树对应的满二叉树编号以便于之后的画图
queue < BST *> q;
if (Tree != NULL)
{
q.push(Tree);//Add root to queue
Mapsequence[countMap++] = Tree->data;//给二叉树中的每一个节点编号
}
while (q.empty() == false) //队列不为空判断
{
//printf("%d → ", q.front()->data);
if (q.front() != NULL)
{
if (q.front()->left_child != NULL) //如果有左孩子,left_Child入队列
{
q.push(q.front()->left_child);
Mapsequence[countMap++] = q.front()->left_child->data;
}
else
{
Mapsequence[countMap++] = -520;//-520表示没有该编号位置没有左节点
q.push(NULL);
}
if (q.front()->right_child != NULL) //如果有右孩子,right_Child入队列
{
q.push(q.front()->right_child);
Mapsequence[countMap++] = q.front()->right_child->data;
}
else
{
Mapsequence[countMap++] = -520;
q.push(NULL);
}
}
else
{
Mapsequence[countMap++] = -520;
Mapsequence[countMap++] = -520;
}
q.pop(); //已经遍历过的节点出队列
}
}
void drawnode(int b, int g, int r)
{
int i = 1;
while (Mapsequence[i++] != 0)
{
if (Mapsequence[i - 1] == -520)continue;
Posfunction(i - 1);
circle(image, Point(pos.x, pos.y), 15, Scalar(b, g, r), -1);
char s[3]; s[0] = (Mapsequence[i - 1] / 10 + '0'); s[1] = (Mapsequence[i - 1] % 10 + '0');
s[2] = '\0';
//putText这个函数是将节点的内容画在节点上
putText(image, s, Point(pos.x, pos.y), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255), 2, 8);
imshow("tree", image);
waitKey(0);
if (Mapsequence[2 * (i - 1)] != -520 && Mapsequence[2 * (i - 1)] != 0)
{
int x = pos.x; int y = pos.y;
Posfunction(2 * (i - 1));
line(image, Point(x, y), Point(pos.x, pos.y), Scalar(255, 255, 255), 2, CV_AA);
imshow("tree", image);
waitKey(0);
}
if (Mapsequence[2 * (i - 1) + 1] != -520 && Mapsequence[2 * (i - 1) + 1] != 0)
{
Posfunction(i - 1);
int x = pos.x; int y = pos.y;
Posfunction(2 * (i - 1) + 1);
line(image, Point(x, y), Point(pos.x, pos.y), Scalar(255, 255, 255), 2, CV_AA);
imshow("tree", image);
waitKey(0);
}
}
}
void Posfunction(int num)
//5层以内满二叉树画法,建立编号与位置坐标的映射(对应关系)
{
if (num < 1)
{
printf("enter num is illeage\n");
exit(1);
}
else if (num == 1)
{
pos.x = 500; pos.y = 50;
return;
}
else if (num == 2 || num == 3)
{
pos.y = 150;
if (num == 2)
pos.x = 300;
else if (num == 3)
pos.x = 700;
return;
}
else if (num >= 4 && num <= 7)
{
pos.y = 250;
pos.x = 200 * (num - 3);
return;
}
else if (num >= 8 && num <= 15)
{
pos.y = 350;
pos.x = 150 + 100 * (num - 8);
return;
}
else if (num >= 16 && num <= 31)
{
pos.y = 550;
pos.x = 125 + 50 * (num - 16);
return;
}
else
{
printf("此画图函数解决不了了!!!\n");
}
}
int Height(BST *T)
//计算树的高度
{
int n, m;
if (T == NULL)
{
return 0;
}
n = Height(T->right_child);
m = Height(T->left_child);
if (m > n)
{
return m + 1;
}
else
{
return n + 1;
}
}
void Calbalance(BST *T)
//递归计算平衡因子
{
if (T == NULL)
{
return;
}
T->bal = Height(T->right_child) - Height(T->left_child);//此处是右树高度减左树高度,在重新平衡的判定中起到作用
Calbalance(T->right_child);
Calbalance(T->left_child);
}
void InsertBalance(BST *x, BST *T)
//传参 parent 是最小不平衡子树的根节点 T是整棵树的根节点指针
//传参类型为指针的地址
{
BST *parent = NULL;
//x节点是插入节点的父亲节点
//若插入节点不是树根结点
if (x)
{
parent = x->parent;//考察插入节点父亲节点的父亲节点
while (parent)//当父亲存在时
{
//失衡节点是parent
if (parent->bal < -1) //当右子树-左子树<-1
{
if (parent->left_child->bal == -1)
{
RotateRight(parent, T);
}
else
{
RotateLR(parent, T);
}
break;
}
if (parent->bal > 1)//当右子树-左子树>1
{
if (parent->right_child->bal == 1)
{
RotateLeft(parent, T);
}
else
{
RotateRL(parent, T);
}
break;
}
else if (parent->bal == 0)
{
break;
}
parent = parent->parent;
}
}
}
void RotateRight(BST *parent, BST *T)
{
//parent为最小不平衡子树的根节点
BST *x = (parent)->parent;//记录父亲节点
BST *SubL = (parent)->left_child;//记录根节点的左孩子
BST *SubLR = SubL->right_child;//根节点左孩子的右孩子
//parent的左孩子为SubLR
parent->left_child = SubLR;
if (SubLR)
{
SubLR->parent = parent;
}
//SubL的右孩子为parent
SubL->right_child = (parent);
parent->parent = SubL;
//若x不存在,则说明parent即是根节点
if (!x)
{
ROOT = SubL;
SubL->parent = NULL;
}
//存在则判断parent是x的左孩子还是右孩子,SubL替换
else {
if (x->left_child == parent)
{
x->left_child = SubL;
}
else
{
x->right_child = SubL;
}
SubL->parent = x;
}
}
void RotateLeft(BST *parent, BST *T) {
BST *x = parent->parent;
BST *SubR = parent->right_child;
BST *SubRL = SubR->left_child;
//parent的右孩子为SubRL
parent->right_child = SubRL;
if (SubRL)
{
SubRL->parent = parent;
}
//SubR的左孩子为parent
SubR->left_child = parent;
parent->parent = SubR;
//x的孩子为SubR
if (!x)//如果x不存在
{
T = SubR;
SubR->parent = NULL;
}
else
{
if (x->left_child == parent)
{
x->left_child = SubR;
}
else
{
x->right_child = SubR;
}
SubR->parent = x;
}
}
void RotateLR(BST *parent, BST *T)
{
//先对SubL进行左转变化、再对parent进行右转变化
RotateLeft(parent->left_child, T);
RotateRight(parent, T);
}
void RotateRL(BST *parent, BST *T)
{
RotateRight(parent->right_child, T);
RotateLeft(parent, T);
}
void Insert(int data)
{
BST *parent = NULL;//记录插入节点的父亲节点
BST *p = ROOT;
if (ROOT == NULL)//第一次插入的时候
{
BST *q = (BST *)malloc(sizeof(BST));
q->bal = 0;
q->data = data;
q->left_child = NULL;
q->parent = NULL;
q->right_child = NULL;
ROOT = q;
}
else
{
//找到插入位置
while (p)
{
parent = p;//记录父亲节点
if (data < p->data)
{
p = p->left_child;
}
else
{
p = p->right_child;
}
}
//创新节点并插入
BST *q = (BST *)malloc(sizeof(BST));
q->bal = 0;
q->data = data;
q->left_child = NULL;
q->parent = NULL;
q->right_child = NULL;
if (data < parent->data)
{
parent->left_child = q;
}
else
{
parent->right_child = q;
}
q->parent = parent;
}
//更新平衡因子并维护平衡
Calbalance(ROOT);
InsertBalance(parent, ROOT);
Calbalance(ROOT);
}
第十二周数据结构作业2(哥们很菜,望大佬指点)
最新推荐文章于 2024-04-29 23:04:15 发布