树的基础概念
1.子树是不想交的;除了根节点之外,每个节点有且仅有一个父节点,一颗N个节点的数有N-1条边
2.节点的度:一个节点含有子树的个数
叶子节点(终端节点):度为0的节点(无孩子节点)
非终端节点(分支节点):度不为0的节点
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点 的父节点
孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点
兄第节点:具有相同父节点的节点互称为兄第节点
树的度:一颗树中,最大的节点的度称为树的度
节点的层次:从根节点开始定义起,根为第一层
树的高度或深度:根节点到最远的叶子结点的层数
堂兄弟节点:双亲在同一层的节点互为堂兄弟节点
森林:由m颗互不相交的树的集合称为森林
二叉树概念及性质
1.二叉树的特点
(1)每个节点最多有两颗子树,即二叉树不存在度大于2的结点
(2)二叉树的子树有左右之分,其子树的次序不能颠倒
2.特殊的二叉树
(1)满二叉树:一个二叉树,每一层的节点数都达到最大值;也就是说,如果一个二叉树的层数为k,且节点总数是(2^k)-1,则它就是满二叉树
(2)完全二叉树:对于深度为k的,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中编号从1到n的节点一一对应时称为完全二叉树。
3.二叉树的性质
(1)根节点的层数为1时,在二叉树的第i层上至多有2^(i-1)
(2)深度为K的二叉树最多有2^k -1
(3)对任何一颗二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1;
(4)具有n个结点的完全二叉树深度为[log2^n]+1 向上取整
(5)具有n个节点的完全二叉树,如果按照从上至下从左到右的数组顺序对所有节点从0开始编号,则对于序号i的节点有:
根从0开始,求其父节点(i-1)/2 2*i+1 左子树 2*i+2 右子树
根从1开始,求其父节点 i/2 2*i左子树 2*i+1 右子树
4.二叉树共有N个节点,度为0的n0不会产生边,度为1的n1产生一条边,度为2的n2产生两条边
节点关系: N=n0+n1+n2 边关系:N-1=n1+n2*2
二叉树的顺序结构
1.顺序结构就是使用数组来存储,一般使用数组只适合表示完全二叉树,通常把堆(一种二叉树)使用顺序结构的数组来存储;普通二叉树利用顺序方式存储,则其空间利用率不高。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。
2.堆也是优先级队列,分为大堆和小堆,大堆为堆中每个节点都比其孩子节点大,堆顶元素一定最大,每条路径都是降序;小堆为堆中每个节点都比起孩子节点小,堆顶元素一定最小,每条路径都是升序。
3.堆的适用场景:获取集合中最大或最小的前K个元素
4.堆的算法
(1)堆的向下调整算法:调整成一个小堆;前提:左右子树必须是一个堆;注意:有没有右子树
(2)堆的创建:从倒数第一个非叶子节点的子树开始调整,一直调整到根节点的树,就可以调整成堆
(3)堆的插入:插入到数组尾部,向上调整算法
(4)堆的删除:删除堆是删除堆顶元素;将堆顶的数据和最后一个数据进行交换,然后删除最后一个数据,再进行向下调整算法
//Common.h
#ifndef _COMMON_H_
#define _COMMON_H_
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <memory.h>
#include <string.h>
#include <vld.h>
#define ElemType int
void Swap(ElemType* x, ElemType* y)
{
ElemType tmp = *x;
*x = *y;
*y = tmp;
}
#endif
//heap.h
#ifndef _HEAP_H_
#define _HEAP_H_
#include "Common.h"
#define HEAP_DEFAULT_SIZE 20
typedef int HeapElemType;
typedef struct MinHeap{
HeapElemType *base;
size_t capacity;
size_t size;
};
void HeapInit(MinHeap *php, int sz = HEAP_DEFAULT_SIZE);
void HeapCreate(MinHeap *php, int ar[], int n);//用数组创建堆
void HeapInsert(MinHeap *php, HeapElemType x);
void HeapErase(MinHeap *php);
void HeapShow(MinHeap *php);
bool HeapEmpty(MinHeap *php);
HeapElemType HeapTop(MinHeap *php);
void HeapSort(MinHeap *php, int ar[], int n);
void HeapShiftUp(MinHeap *php, int start);
void HeapShiftDown(MinHeap *php, int start, int n);
void HeapInit(MinHeap *php, int sz = HEAP_DEFAULT_SIZE)
{
assert(php != NULL);
php->capacity = sz > HEAP_DEFAULT_SIZE ? sz : HEAP_DEFAULT_SIZE;
php->base = (HeapElemType*)malloc(sizeof(HeapElemType)*php->capacity);
memset(php->base, 0, sizeof(HeapElemType) * php->capacity);
php->size = 0;
}
//用数组创建堆
void HeapCreate(MinHeap *php, int ar[], int n)
{
//先把数组放入堆中
php->capacity = n;
php->base = (HeapElemType*)malloc(sizeof(HeapElemType)*php->capacity);
assert(php->base != NULL);
for (int i = 0; i < n; i++)
php->base[i] = ar[i];
php->size = n;
//对堆进行调整 找到其最后一个分支 向下调整
int curpos = n / 2 - 1;
while (curpos >=0)
{
HeapShiftDown(php, curpos, n);
curpos--;
}
}
void HeapInsert(MinHeap *php, HeapElemType x)
{
assert(php != NULL);
if (php->size >= php->capacity)
{
printf("堆空间已满,%d不能插入\n");
}
php->base[php->size] = x;
HeapShiftUp(php, php->size);
php->size++;
}
void HeapErase(MinHeap *php)
{
assert(php != NULL);
if (php->size == 0)
{
printf("堆已空,不能删除堆顶元素\n");
return;
}
//删除是从堆顶元素开始删除
php->size--;
php->base[0] = php->base[php->size];
HeapShiftDown(php, 0, php->size);
}
void HeapShow(MinHeap *php)
{
assert(php != NULL);
for (int i = 0; i < php->size;i++)
printf("%d ", php->base[i]);
printf("\n");
}
bool HeapEmpty(MinHeap *php)
{
assert(php != NULL);
return php->size == 0;
}
HeapElemType HeapTop(MinHeap *php)
{
assert(php != NULL&&php->size>0);
return php->base[0];
}
//向下排序
void HeapSort(MinHeap *php, int ar[], int n)
{
HeapCreate(php, ar, n);
while (php->size > 0)
{
php->size--;
Swap(&php->base[php->size], &php->base[0]);
HeapShiftDown(php, 0, php->size);
}
for (int i = 0; i < n; i++)
{
ar[i] = php->base[i];
}
}
//插入数据在尾部 然后向上 调成小堆
void HeapShiftUp(MinHeap *php, int start)//i=parent j=child
{
assert(php != NULL);
int j = start;
int i = (j - 1) / 2;
while (j>0)
{
if (php->base[j] < php->base[i])
{
Swap(&php->base[j], &php->base[i]);
j = i;
i = (j - 1) / 2;
}
else
{
break;
}
}
}
//删除后 向下 调成小堆
void HeapShiftDown(MinHeap *php, int start, int n)
{
//i=parent j=child
int i = start;
int j = 2 * i + 1;//左孩子
while (j<n)
{
//找左右子树的最小值 和最小的那个进行交换 要考虑右树是否存在 不存在就不需要进行比较
if (j + 1 < n&&php->base[j] > php->base[j + 1])
{
j++;
}
if (php->base[i] > php->base[j])
{
Swap(&php->base[i], &php->base[i]);
i = j;
j = 2 * i + 1;
}
else{
break;
}
}
}
#endif
//main.cpp
#include "heap.h"
void Test()
{
//用数组创建堆
int ar[] = { 27, 15, 19, 18, 28, 34, 65, 49, 25, 37 };
int n = sizeof(ar) / sizeof(ar[0]);
MinHeap mhp;
HeapCreate(&mhp, ar, n);
HeapSort(&mhp, ar, n);
HeapShow(&mhp);
}
int main()
{
int ar[] = { 27, 15, 19, 18, 28, 34, 65, 49, 25, 37 };
int n = sizeof(ar) / sizeof(ar[0]);
MinHeap mhp;
HeapInit(&mhp);
for (int i = 0; i < n; ++i)
{
HeapInsert(&mhp, ar[i]);
}
HeapShow(&mhp);
HeapInsert(&mhp, 17);
HeapShow(&mhp);
system("pause");
return 0;
}
二叉树的链式结构
1.遍历方式:先序遍历(根左右)、中序遍历(左根右)、后序遍历(左右根)、层次遍历(自上而下,自左至右逐层访问树的结点的过程)
//Common.h
#ifndef _COMMON_H_
#define _COMMON_H_
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <malloc.h>
#include <vld.h>
#endif _COMMON_H_
//bintree.h
#ifndef _BINTREE_H_
#define _BINTREE_H_
#include "Common.h"
///
struct BinTreeNode;
typedef BinTreeNode* LinkQueueElemType;
typedef struct LinkQueueNode
{
LinkQueueElemType data;
struct LinkQueueNode *link;
}LinkQueueNode;
typedef struct LinkQueue
{
LinkQueueNode *head; // 队头指针
LinkQueueNode *tail; // 队尾指针
}LinkQueue;
void LinkQueueInit(LinkQueue *pq);
void LinkQueueEn(LinkQueue *pq, LinkQueueElemType x);
void LinkQueueDe(LinkQueue *pq);
LinkQueueElemType LinkQueueFront(LinkQueue *pq);
int LinkQueueSize(LinkQueue *pq);
bool LinkQueueEmpty(LinkQueue *pq);
void LinkQueueDestroy(LinkQueue *pq);
/
void LinkQueueInit(LinkQueue *pq)
{
assert(pq != NULL);
pq->head = pq->tail = NULL;
}
void LinkQueueEn(LinkQueue *pq, LinkQueueElemType x)
{
assert(pq != NULL);
LinkQueueNode *node = (LinkQueueNode*)malloc(sizeof(LinkQueueNode));
assert(node != NULL);
node->data = x;
node->link = NULL;
if (pq->head == NULL)
pq->head = pq->tail = node;
else
{
pq->tail->link = node;
pq->tail = node;
}
}
void LinkQueueDe(LinkQueue *pq)
{
assert(pq != NULL);
if (pq->head != NULL)
{
LinkQueueNode *p = pq->head;
if (pq->head == pq->tail)
pq->head = pq->tail = NULL;
else
pq->head = p->link;
free(p);
}
}
LinkQueueElemType LinkQueueFront(LinkQueue *pq)
{
assert(pq != NULL);
assert(pq->head != NULL);
return pq->head->data; //return pq->tail->data
}
int LinkQueueSize(LinkQueue *pq)
{
assert(pq != NULL);
int size = 0;
LinkQueueNode *p = pq->head;
while (p != NULL)
{
size++;
p = p->link;
}
return size;
}
bool LinkQueueEmpty(LinkQueue *pq)
{
assert(pq != NULL);
return pq->head == NULL;
}
void LinkQueueDestroy(LinkQueue *pq)
{
assert(pq != NULL);
LinkQueueNode *p = pq->head;
while (p != NULL)
{
pq->head = p->link;
free(p);
p = pq->head;
}
}
/
//链栈
typedef BinTreeNode* LinkSstackElemType;
typedef struct LinkStackNode
{
LinkSstackElemType data;
struct LinkStackNode *link;
}LinkStackNode;
typedef LinkStackNode* LinkStack;
void LinkStackInit(LinkStack *pst);
void LinkStackPush(LinkStack *pst, LinkSstackElemType x);
void LinkStackPop(LinkStack *pst);
LinkSstackElemType LinkStackTop(LinkStack *pst);
void LinkStackShow(LinkStack *pst);
int LinkStackSize(LinkStack *pst);
void LinkStackDestroy(LinkStack *pst);
bool LinkStackEmpty(LinkStack *pst);
/
void LinkStackInit(LinkStack *pst)
{
assert(pst != NULL);
*pst = NULL;
}
void LinkStackPush(LinkStack *pst, LinkSstackElemType x)
{
assert(pst != NULL);
LinkStackNode *node = (LinkStackNode*)malloc(sizeof(LinkStackNode));
assert(node != NULL);
node->data = x;
node->link = *pst;
*pst = node;
}
void LinkStackPop(LinkStack *pst)
{
assert(pst != NULL);
if (*pst != NULL)
{
LinkStackNode *p = *pst;
*pst = p->link;
free(p);
}
}
LinkSstackElemType LinkStackTop(LinkStack *pst)
{
assert(pst != NULL && *pst != NULL);
return (*pst)->data;
}
void LinkStackShow(LinkStack *pst)
{
assert(pst != NULL);
LinkStackNode *p = *pst;
while (p != NULL)
{
printf("| %d |\n", p->data);
p = p->link;
}
printf(" -- \n");
}
int LinkStackSize(LinkStack *pst)
{
assert(pst != NULL);
int size = 0;
LinkStackNode *p = *pst;
while (p != NULL)
{
size++;
p = p->link;
}
return size;
}
void LinkStackDestroy(LinkStack *pst)
{
assert(pst != NULL);
LinkStackNode *p = *pst;
while (p != NULL)
{
*pst = p->link;
free(p);
p = *pst;
}
}
bool LinkStackEmpty(LinkStack *pst)
{
assert(pst != NULL);
return *pst == NULL;
}
///
//二叉树
typedef char BinTreeElemType;
typedef struct BinTreeNode{
BinTreeElemType data;
struct BinTreeNode* leftChild;
struct BinTreeNode* rightChild;
}BinTreeNode;
typedef BinTreeNode* BinTree;
//二叉树的创建
void BinTreeInit(BinTree* t);
void BinTreeCreate(BinTree* t);
BinTree BinTreeCreate_1();
BinTree BinTreeCreate_2(const char *s, int *i);
BinTree BinTreeCreate_3(const char* vlr, const char* lvr, int n);//根据前序遍历和中序遍历 创建二叉树
BinTree BinTreeCreate_4(const char* lrv, const char* lvr, int n);//根据中序遍历和后续遍历 创建二叉树
//二叉树的遍历
void BinTreeVLR(BinTree t);
void BinTreeLVR(BinTree t);
void BinTreeLRV(BinTree t);
void BinTreeLevel(BinTree t);//层序遍历
//二叉树的非递归遍历 需要用到栈
void BinTreeVLR_Nor(BinTree t);
void BinTreeLVR_Nor(BinTree t);
void BinTreeLRV_Nor(BinTree t);
//二叉树的算法
int Size(BinTree t);
int Height(BinTree t);
BinTreeNode* Left(BinTreeNode *p);
BinTreeNode* right(BinTreeNode *p);
BinTreeNode* BinTreeParent(BinTree t, BinTreeNode *p);
BinTreeNode* BinTreeFind(BinTree t, BinTreeElemType key);
BinTreeNode* BinTreeClone(BinTree t);
bool Equal(BinTree t1, BinTree t2);
//
//二叉树的创建
void BinTreeInit(BinTree* t)//BinTreeNode** t
{
*t = NULL;
}
//不带返回值的方式
void BinTreeCreate(BinTree* t)
{
assert(t != NULL);
BinTreeElemType item;
scanf("%c", &item);
if (item == '#')
{
*t = NULL;
}
else{
*t = (BinTreeNode*)malloc(sizeof(BinTreeNode));
assert(*t != NULL);
(*t)->data = item;
BinTreeCreate(&(*t)->leftChild);
BinTreeCreate(&(*t)->rightChild);
}
}
//用返回值的方式
BinTree BinTreeCreate_1()
{
BinTreeElemType item;
scanf("%c", &item);
if (item == '#')
{
return NULL;
}
else{
BinTreeNode* t = (BinTreeNode*)malloc(sizeof(BinTreeNode));
assert(t != NULL);
t->data = item;
t->leftChild = BinTreeCreate_1();
t->rightChild = BinTreeCreate_1();
return t;
}
}
//当二叉树的数据放在数组里时
BinTree BinTreeCreate_2(const char *s, int *i)
{
assert(s != NULL);
//数组为空或者为#时返回空
if (s[*i] == '#'||s[*i]=='\0')
{
return NULL;
}
else{
BinTreeNode* t = (BinTreeNode*)malloc(sizeof(BinTreeNode));
assert(t != NULL);
t->data = s[*i];
(*i)++;
t->leftChild = BinTreeCreate_2(s, i);
(*i)++;
t->rightChild = BinTreeCreate_2(s, i);
return t;
}
}
//根据前序遍历和中序遍历 创建二叉树
BinTree BinTreeCreate_3(const char* vlr, const char* lvr, int n)
{
if (n == 0)
return NULL;
int k = 0;//标记根节点
while (vlr[0] != vlr[k])
{
k++;
}
BinTreeNode* t = (BinTreeNode*)malloc(sizeof(BinTreeNode));
t->data = vlr[0];
t->leftChild = BinTreeCreate_3(vlr + 1, lvr, k);
t->rightChild = BinTreeCreate_3(vlr + k + 1, lvr + k + 1, n - k - 1);
return t;
}
//二叉树的遍历
void BinTreeVLR(BinTree t)
{
if (t != NULL)
{
printf("%c", t->data);
BinTreeVLR(t->leftChild);
BinTreeVLR(t->rightChild);
}
}
void BinTreeLVR(BinTree t)
{
if (t != NULL)
{
BinTreeLVR(t->leftChild);
printf("%c", t->data);
BinTreeLVR(t->rightChild);
}
}
void BinTreeLRV(BinTree t)
{
if (t != NULL)
{
BinTreeLRV(t->leftChild);
BinTreeLRV(t->rightChild);
printf("%c", t->data);
}
}
//层序遍历 用队列进行 父节点出栈 左右孩子不为空就进队列
void BinTreeLevel(BinTree t)
{
if (t != NULL){
LinkQueue Q;
LinkQueueInit(&Q);
LinkQueueEn(&Q, t);
while (!LinkQueueEmpty(&Q))
{
BinTreeNode *p = LinkQueueFront(&Q);
LinkQueueDe(&Q);
printf("%c ", p->data);
if (p->leftChild != NULL)
{
LinkQueueEn(&Q, p->leftChild);
}
if (p->rightChild != NULL)
{
LinkQueueEn(&Q, p->rightChild);
}
}
LinkQueueDestroy(&Q);
}
}
//二叉树的非递归遍历 需要用到栈
void BinTreeVLR_Nor(BinTree t)
{
if (t != NULL)
{
LinkStack st;
LinkStackInit(&st);
LinkStackPush(&st, t);
while (!LinkStackEmpty(&st))
{
BinTreeNode *p = LinkStackTop(&st);
LinkStackPop(&st);
printf("%c ", p->data);
if (p->rightChild != NULL)
LinkStackPush(&st, p->rightChild);
if (p->leftChild != NULL)
LinkStackPush(&st, p->leftChild);
}
LinkStackDestroy(&st);
}
}
//左树为空出栈访问 然后观察右树 如果右树不为空指向右树
void BinTreeLVR_Nor(BinTree t)
{
if (t != NULL){
LinkStack st;
LinkStackInit(&st);
do{
while (t != NULL)
{
LinkStackPush(&st, t);
t = t->leftChild;
}
BinTreeNode* p = LinkStackTop(&st);
LinkStackPop(&st);
printf("%c ", p->data);
if (p->rightChild != NULL)
{
t = p->rightChild;
}
} while (!LinkStackEmpty(&st) || t != NULL);
}
}
//右树访问过了才能访问根节点 用两个指针
void BinTreeLRV_Nor(BinTree t)
{
if (t != NULL)
{
LinkStack st;
LinkStackInit(&st);
BinTreeNode *pre = NULL;
do
{
while (t != NULL)
{
LinkStackPush(&st, t);
t = t->leftChild;
}
BinTreeNode *p = LinkStackTop(&st);
if (p->rightChild == NULL || p->rightChild == pre)
{
LinkStackPop(&st);
printf("%c ", p->data);
pre = p;
}
else
t = p->rightChild;
} while (!LinkStackEmpty(&st));
}
}
//二叉树的算法
int Size(BinTree t)
{
if (t == NULL)
{
return 0;
}
else{
return Size(t->leftChild) + Size(t->rightChild) + 1;
}
}
int Height(BinTree t)
{
if (t == NULL)
{
return 0;
}
else{
int left_h = Height(t->leftChild);
int right_h = Height(t->rightChild);
return (left_h > right_h ? left_h : right_h) + 1;
}
}
//找该节点的孩子节点
BinTreeNode* Left(BinTreeNode *p)
{
assert(p != NULL);
return p->leftChild;
}
BinTreeNode* right(BinTreeNode *p)
{
assert(p != NULL);
return p->rightChild;
}
BinTreeNode* BinTreeParent(BinTree t, BinTreeNode *p)
{
//要找该节点的父节点
//考虑特殊情况 t==p说明是树顶
if (t == NULL || p == NULL || t == p)
{
return NULL;
}
//树顶元素就是其父节点
if (t->leftChild == p || t->rightChild == p)
{
return t;
}
BinTreeNode* pr = BinTreeParent(t->leftChild, p);
if (pr != NULL)
{
return pr;
}
return BinTreeParent(t->rightChild, p);
}
BinTreeNode* BinTreeFind(BinTree t, BinTreeElemType key)
{
if (t == NULL || t->data == key)
{
return t;
}
BinTreeNode* p = BinTreeFind(t->leftChild, key);
if (p != NULL)
{
return p;
}
return BinTreeFind(t->rightChild, key);
}
//拷贝
BinTreeNode* BinTreeClone(BinTree t)
{
if (t == NULL)
{
return NULL;
}
else{
BinTreeNode* bt = (BinTreeNode*)malloc(sizeof(BinTreeNode));
assert(bt != NULL);
bt->data = t->data;
bt->leftChild=BinTreeClone(t->leftChild);
bt->rightChild = BinTreeClone(t->rightChild);
return bt;
}
}
//值相等 并且地址相等
bool Equal(BinTree t1, BinTree t2)
{
if (t1 == NULL&&t2 == NULL)
return true;
if (t1 == NULL || t2 == NULL)
return false;
return (t1->data == t2->data&&Equal(t1->leftChild, t2->leftChild) && Equal(t1->rightChild, t2->rightChild));
}
#endif _BINTREE_H_
//main.cpp
#include "bintree.h"
int main()
{
const char *str = "ABC##DE##F##G#H##";
BinTree bt;
BinTreeInit(&bt);
//BinTreeCreate(&bt);
//bt=BinTreeCreate_1();
int index = 0;
bt = BinTreeCreate_2(str, &index);
//先序遍历
printf("VLR: ");
BinTreeVLR(bt);
printf("\n");
//中序遍历
printf("VLR: ");
BinTreeLVR(bt);
printf("\n");
//后序遍历
printf("VLR: ");
BinTreeLRV(bt);
printf("\n");
//层次遍历
printf("Level: ");
BinTreeLevel(bt);
printf("\n");
printf("size = %d\n", Size(bt));
printf("height = %d\n", Height(bt));
char key = 'A';
BinTreeNode *p = BinTreeFind(bt, key);
BinTreeNode *pr = BinTreeParent(bt, p);
system("pause");
return 0;
}
2.二叉搜索树 (二叉排序树)左子树比根小,右子树比根大 中序遍历得到从小到大的排序,时间复杂度为log2^n
//Common.h
#ifndef _COMMON_H_
#define _COMMON_H_
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <vld.h>
#endif
//bst.h
#ifndef _BST_H_
#define _BST_H_
#include "Common.h"
typedef int BstElemType;
//二叉搜索树/二叉排序树 原因:映射节点到地面就是从小到大的排序
//并且左子树比根小 右子树比根大
typedef struct BSTNode{
BstElemType data;
struct BSTNode* leftChild;
struct BSTNode* rightChild;
}BSTNode;
typedef BSTNode* BSTree;
void BstInit(BSTree* bst);
bool BstInsert(BSTree* bst,BstElemType x);
BstElemType BstMin(BSTree t);
BstElemType BstMax(BSTree t);
void BstSortPrint(BSTree t);
BSTNode* BstFind(BSTree t, BstElemType key);
bool BstErase(BSTree *t, BSTNode *p);
/
void BstInit(BSTree* bst)
{
*bst = NULL;
}
bool BstInsert(BSTree* bst, BstElemType x)
{
//左子树放比根小的 右子树放比根大的
//当没有节点存在时
if (*bst == NULL){
*bst = (BSTNode*)malloc(sizeof(BSTNode));
(*bst)->data = x;
(*bst)->leftChild = (*bst)->rightChild = NULL;
return true;
}
if (x < (*bst)->data)
{
return BstInsert(&(*bst)->leftChild, x);
}
else{
return BstInsert(&(*bst)->rightChild, x);
}
}
BstElemType BstMin(BSTree t)
{
assert(t != NULL);
while (t->leftChild != NULL)
{
t = t->leftChild;
}
return t->data;
}
BstElemType BstMax(BSTree t)
{
assert(t != NULL);
while (t->rightChild != NULL)
{
t = t->rightChild;
}
return t->data;
}
//按中序遍历方式打印
void BstSortPrint(BSTree t)
{
if (t != NULL)
{
BstSortPrint(t->leftChild);
printf("%d ", t->data);
BstSortPrint(t->rightChild);
}
}
//查找
BSTNode* BstFind(BSTree t, BstElemType key)
{
if (t == NULL)
{
return NULL;
}
if (key == t->data)
{
return t;
}
if (key < t->data)
{
return BstFind(t->leftChild, key);
}
else {
return BstFind(t->rightChild, key);
}
}
//可能的情况:叶子节点、具有一个左树的节点、具有一个右树的节点、具有左右数的节点
bool BstErase(BSTree *t, BSTNode *p)
{
if (*t != NULL)
{
if ((*t)->data > p->data)
{
BstErase(&(*t)->leftChild, p);
}
else if ((*t)->data < p->data)
{
BstErase(&(*t)->rightChild, p);
}
else{
//删除
//叶子结点
if (p->leftChild == NULL && p->rightChild == NULL)
{
free(*t);
*t = NULL;
}
else if (p->leftChild != NULL&&p->rightChild == NULL)
{
//具有一个左树的节点
*t = p->leftChild;
free(p);
}
else if (p->rightChild != NULL&&p->leftChild == NULL)
{
//具有一个右树的节点
*t = p->rightChild;
free(p);
}
else{
//具有左右树的节点 找前驱或者后继(中序遍历)
BSTNode* s = p->leftChild;
while (s->rightChild != NULL)
s = s->rightChild;
p->data = s->data;
BstErase(&p->leftChild, s);
}
}
}
}
#endif
//main.cpp
#include "bst.h"
int main()
{
int ar[] = { 27, 15, 19, 18, 1, 28, 34, 65, 100, 49, 25, 37 };
int n = sizeof(ar) / sizeof(ar[0]);
BSTree bst;
BstInit(&bst);
for (int i = 0; i < n; i++)
{
BstInsert(&bst, ar[i]);
}
printf("min=%d\n", BstMin(bst));
printf("max=%d\n", BstMax(bst));
BstSortPrint(bst);
printf("\n");
BSTNode *p = BstFind(bst, 28);
BstErase(&bst, p);
return 0;
}