数据结构6-二叉树

树的基础概念

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;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值