树
树的一些术语
树的性质
树的分类
-
完全二叉树------------若设二叉树的高度为 h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层有叶 子节点,并且叶子结点都是从左到右依次排布,这就是完全二叉树(堆就是完全二叉树)
-
满二叉树------------除了叶结点外每一个结点都有左右子节点且叶子结点都处在最底层的二叉树
-
平衡二叉树------------又被称为 AVL 树,它是一颗空树或左右两个子树的高度差的绝对值不超过 1,并且左右两个子树都 是一棵平衡二叉树
-
二叉搜索树------------又称二叉查找树、二叉排序树(Binary Sort Tree)。它是一颗空树或是满足下列性质的二叉
- 红黑树------------是一种自平衡二叉搜索树,是AVL树和二叉排序树的一种变种,红黑树的左右子树的结点的比例不会超过1:2。除了满足排序树的性质外,还要满足以下的性质,以保持红黑树的平衡
二叉树的实现
#pragma once
#include <iostream>
#define isLess(a,b) (a<b)
#define isEqual(a,b) (a==b)
//typedef int DataType;
struct Tree {
int value;
Tree* Left, * Right;
};
bool insertTree(Tree** root, int value);
int findMax(Tree* root);
int findMin(Tree* root);
Tree* QueryByRec(Tree* root,int value);
Tree* QueryByLoop(Tree* root, int value);
Tree* QueryParent(Tree* root, int value);
void clearTree(Tree* root);
void delNode(Tree* root, int value);
void preOrderRec(Tree* root);
void midOrderRec(Tree* root);
void backOrderRec(Tree* root);
void preOrder(Tree* root);
#include "Tree.h"
#include "Stack.h"
bool insertTree(Tree** root, int value) {
Tree* Node = new Tree;
if (Node == NULL) {
return false;
}
Node->Right = Node->Left = NULL;
Node->value = value;
Tree* tmp = NULL;//保存当前结点
Tree* parent = NULL;//当前结点的父节点
bool isLeft = true;//是否在左节点插入值
if (*root) {//存在根节点
tmp = *root;
}
else {//不存在根节点,直接让他成为根节点
*root = Node;
return true;
}
while (tmp) {
parent = tmp;
if (isLess(Node->value, tmp->value)) {
tmp = tmp->Left;//向左移动
isLeft = true;
}
else {
tmp = tmp->Right;
isLeft = false;
}
}
if (isLeft) {
parent->Left = Node;
}
else {
parent->Right = Node;
}
return true;
}
void preOrderRec(Tree* root) {
if (root == NULL) {
return;
}
printf("%d ", root->value);
preOrderRec(root->Left);
preOrderRec(root->Right);
}
void midOrderRec(Tree* root) {
if (root == NULL) {
return;
}
midOrderRec(root->Left);
printf("%d ", root->value);
midOrderRec(root->Right);
}
void backOrderRec(Tree* root) {
if (root == NULL) {
return;
}
backOrderRec(root->Left);
backOrderRec(root->Right);
printf("%d ", root->value);
}
void preOrder(Tree* root) {
if (root == NULL) {
return;
}
Stack *S;
Tree node;
initStack(S);
push(S, *root);//将首元素入栈
while (!isEmpty(S)) {
node = top(S);
cout << node.value << " ";
pop(S);
if (node.Right!=NULL) {
push(S,*node.Right);
}
if (node.Left!=NULL) {
push(S, *node.Left);
}
}
cout << endl;
clearStack(S);
}
int findMax(Tree* root) {
if (root->Right == NULL) {
return root->value;
}
return findMax(root->Right);
}
int findMin(Tree* root) {
if (root->Left == NULL) {
return root->value;
}
return findMin(root->Left);
}
Tree* QueryByRec(Tree* root, int value) {
if (root==NULL||isEqual(root->value, value)) {
return root;
}
else if (isLess(root->value, value)) {
return QueryByRec(root->Right, value);
}
else {
return QueryByRec(root->Left, value);
}
}
Tree* QueryByLoop(Tree* root, int value) {
if (root == NULL) {
return root;
}
while (true) {
if (root==NULL||isEqual(root->value, value)) {
return root;
}
else if (isLess(root->value, value)) {
root = root->Right;
}
else {
root = root->Left;
}
}
}
Tree* QueryParent(Tree* root, int value) {
if (root == NULL) {
return root;
}
if ((root->Left && isEqual(root->Left->value, value))
||(root->Right && isEqual(root->Right->value, value))) {
return root;
}
else if (root->Right && isLess(root->value, value)) {
QueryParent(root->Right, value);//向右边走
}
else if (root->Left && isLess(value, root->value)) {
QueryParent(root->Left, value);//向左边走
}
else {
return NULL;//没有父节点
}
}
void delNode(Tree* root, int value) {
if (root == NULL) {
return;
}
Tree* node = QueryByRec(root, value);
if (node == NULL) {
cout << "没有要删除的结点!" << endl;
return;
}
if (root->Left == NULL && root->Right == NULL) {//这棵树只有一个结点
delete root;
root = NULL;
return;
}
Tree* parent = QueryParent(root, value);//找到要删除结点的父节点
if (node->Left == NULL && node->Right == NULL) {//删除的为叶子结点
if (parent->Left && isEqual(parent->Left->value, value)) {
delete parent->Left;
parent->Left = NULL;
}
else if (parent->Right && isEqual(parent->Right->value, value)) {
delete parent->Right;
parent->Right = NULL;
}
}
else if (node->Left && node->Right) {//删除的结点存在左右子节点
int min = findMin(node->Right);
node->value = min;//使用右子树中最小的值来替代
delNode(node->Right, min);//再将原来的值删掉
}
else {//只有一个子树的结点
if (node->Left) {
if (parent->Left && isEqual(parent->Left->value, value)) {
parent->Left = node->Left;
delete node;
}
else if (parent->Right && isEqual(parent->Right->value, value)) {
parent->Right = node->Left;
delete node;
}
}
else {
if (parent->Left && isEqual(parent->Left->value, value)) {
parent->Left = node->Right;
delete node;
}
else {
parent->Right = node->Right;
delete node;
}
}
}
}
void clearTree(Tree* root) {
if (root) {
clearTree(root->Left);
clearTree(root->Right);
delete root;
}
}
哈夫曼编码
哈夫曼编码是基于二叉树构建编码来压缩结构的一种编码,算法根据字符出现的频率,重新对字符进行编码
队列代码
#pragma once
#include "Tree.h"
#define MAX_SIZE 128
typedef Tree* DataType;
struct Node {
int priority;
DataType data;
Node* next;//下一个结点
};
struct Queue {
int length;
Node *front;
Node* rear;//尾指针
};
bool initQueue(Queue*& Q);
bool isEmpty(Queue* Q);
bool isFull(Queue* Q);
bool push(Queue*& Q,DataType data,int priority);
bool pop(Queue*& Q,DataType *data);
DataType getHead(Queue*& Q);
int getSize(Queue* Q);
void clearQueue(Queue*& Q);
void printQueue(Queue*& Q);
#include <iostream>
#include "Queue.h"
bool initQueue(Queue*& Q) {
Q = new Queue;
if (Q == NULL) {
return false;
}
Q->length = 0;
Q->front = Q->rear = NULL;
return true;
}
bool isEmpty(Queue* Q) {
if (Q->length) {
return false;
}
return true;
}
bool isFull(Queue* Q) {
if (Q->length == MAX_SIZE) {
return true;
}
return false;
}
bool push(Queue*& Q,DataType data,int priority) {
if (!Q||isFull(Q)) {
return false;
}
Node* node = new Node;
if (node == NULL) {
return false;
}
node->data = data;
node->priority = priority;
node->next = NULL;
if (isEmpty(Q)) {//队列为空
Q->front = Q->rear = node;
++Q->length;
return true;
}
/*Q->rear->next = node;
Q->rear = node;*/
node->next = Q->front;//在头部插入数据
Q->front = node;
++Q->length;
return true;
}
bool pop(Queue*& Q,DataType *data) {
if (!Q||isEmpty(Q)) {
return false;
}
Node** prev = &Q->front;
Node* prev_node = Q->front;
Node* last = Q->front;
Node* tmp = last->next;
while (tmp) {
if (tmp->priority <(*prev)->priority) {//优先级更小的先出队
prev = &last->next;//指向删除结点的前一个结点的next指针
prev_node = last;//指向删除结点的前一个结点
}
last = tmp;
tmp = tmp->next;
}
tmp =*prev;
*data = tmp->data;
(*prev) = (*prev)->next;
delete tmp;
--Q->length;
if (isEmpty(Q)) {
Q->rear = NULL;
}
if (prev_node && prev_node->next == NULL) {//删除的是最后一个结点
Q->rear = prev_node;
}
return true;
}
DataType getHead(Queue*& Q) {
if (isEmpty(Q)) {
return DataType();
}
return Q->front->data;
}
int getSize(Queue* Q) {
return Q->length;
}
void clearQueue(Queue*& Q) {
if (isEmpty(Q)) {
delete Q;
return;
}
Node* p, * q;
p = Q->front;
while (p) {
q = p->next;
delete p;
p = q;
}
delete Q;
return;
}
void printQueue(Queue*& Q) {
if (isEmpty(Q)) {
return;
}
Node* p;
p = Q->front;
while (p!=NULL) {
std::cout << p->data->value<<"[" << p->data->weight << "]\t";
p = p->next;
}
std::cout <<std:: endl;
/*Node* p = Q->front;
for (int i = 0; i != Q->length; ++i) {
std::cout << p->data->value << '\t' << p->data->weight << std::endl;
p = p->next;
}*/
}
哈夫曼代码
#pragma once
struct Tree {
char value;
int weight;//权值
Tree* parent;
Tree* left;
Tree* right;
};
void HuffmanTree(Tree*& T, int n);//构建哈夫曼树
void preOrderRec(Tree* T);
#include<iostream>
using namespace std;
#include "Tree.h"
#include "Queue.h"
void HuffmanTree(Tree* &T, int n) {
Queue* Q;
initQueue(Q);
for (int i = 0; i != n; ++i) {
Tree* node=new Tree;
cout << "请输入第" << i + 1 << "个元素和出现的频率" << endl;
cin >> node->value >> node->weight;
node->parent = node->right = node->left = NULL;
push(Q, node, node->weight);
}
printQueue(Q);
while (true) {
DataType node1 = NULL;
DataType node2 = NULL;
if (!isEmpty(Q)) {
pop(Q, &node1);//弹出第一个元素
}
else {
break;
}
if (!isEmpty(Q)) {
DataType node3 = new Tree;
pop(Q, &node2);//弹出第二个元素
node3->value = ' ';
node3->weight = node1->weight + node2->weight;
node3->left = node1;
node3->right = node2;
node1->parent = node2->parent = node3;
push(Q, node3, node3->weight);
}
else {//只剩最后一个元素
T = node1;
break;
}
}
}
void preOrderRec(Tree* T) {
if (T == NULL) {
return;
}
cout << T->value <<"[" << T->weight <<"]\t";
preOrderRec(T->left);
preOrderRec(T->right);
}