MyCDay12

文章介绍了二叉搜索树(BST)的基本操作,包括查找、插入和删除,以及遍历方法如深度优先搜索和广度优先搜索。对于完全二叉树和高度为h的二叉树,讨论了节点数量的范围。同时提到了平衡二叉搜索树,如AVL树和红黑树,它们保证了更高效的查找性能。
摘要由CSDN通过智能技术生成

1.树的基本操作

  • 查找:先取根结点,如果它等于我们要查找的数就返回;如果查找的数据比根节点小,就在左子树中递归查找;如果要查找的数据比根结点大,那么就在右子树中递归查找。

  • 插入:如果要插入的数据比结点大,并且结点的右子树为空,就将新数据直接插到右孩子的位置;如果不为空,就再递归遍历右子树,查找插入位置。同理,如果要插入的数据比结点小,并且结点的左子树为空,就将新数据插入到左孩子的位置;如果不为空,就再递归遍历左子树,查找插入位置。

  • 删除:分三种情况处理
    a. 如果要删除结点没有孩子,那么直接将该结点删除就行了。
    b. 如果要删除结点只有一个孩子,那么需要就父亲结点对应的指针,指向孩子结点。
    c. 如果要删除结点有两个孩子,那么我们可以找到这个结点的右子树中最小结点 (或者 左子树中最大结点),把它替换到要删除的结点上,然后再删除掉这个最小结点。
    在这里插入图片描述

2.遍历

  1. 深度优先搜索遍历
    • 先序DLR
    • 中序LDR
    • 后序LRD
  2. 广度优先遍历
    在这里插入图片描述
    1. 将根节点入队列
    2. 判断队列是否为空
      • 是:结束遍历
      • 否:出队列(判断出对队列的结点是否有左孩子,有:将左孩子入队列;判断是否有右孩子,有:将右孩子出对列)返回2

结论:树的增删查的时间复杂度为O(h),h为树的高度。

问题:根为第一层

  1. n个结点,高度最低为多少?
    完全二叉树, log(n+1)
  2. n个节点的完全二叉树,其高度为多少?
    log(n+1)向上取整
  3. 高度为h的二叉树,节点数目范围是
    2h-1 ~~2h-1

二叉树的基本操作 中序遍历 层次遍历

BST.h

#pragma once
#include<stdbool.h>

typedef char K;

typedef struct tree_node {
	K key;
	struct tree_node* left;
	struct tree_node* right;
}TreeNode;

typedef struct {
	TreeNode* root;
}BST;

//API

BST* bst_create();

bool bst_insert(BST* tree, K key);
bool bst_find(BST* tree, K key);
bool bst_delete(BST* tree, K key);

Queue.h

#pragma once

#include<stdbool.h>
#define N 10

typedef struct tree_node* E;

typedef struct {
	E elements[N];
	int front;
	int rear;
	int size;
}Queue;

Queue* create_queue();
void destroy_queue(Queue* q);

void enqueue(Queue* q, E val);
E dequeue(Queue* q);
E peek(Queue* q);
int size(Queue* q);

bool isEmpty(Queue* q);
bool isFull(Queue* q);

BST.c

#include "BST.h"
#include"Queue.h"
#include <stdio.h>
#include<stdlib.h>

BST* bst_create() {
	return calloc(1, sizeof(BST));
}

bool bst_insert(BST* tree, K key) {
	TreeNode* parent = NULL;
	TreeNode* curr = tree->root;

	int cmp = 0;
	while (curr != NULL) {
		cmp = key - curr->key;
		if (cmp == 0) {
			return false;
		}
		else if (cmp < 0) {//往左走
			parent = curr;
			curr = curr->left;
		}
		else { //往右走
			parent = curr;
			curr = curr->right;
		}
	}
	//插入结点
	TreeNode* newNode = (TreeNode*)calloc(1, sizeof(TreeNode));
	if (newNode == NULL) {
		printf("calloc failed in bst_insert\n");
		exit(1);
	}
	//初始化
	newNode->key = key;
	//链接
	if(parent==NULL){//空树
		tree->root = newNode;
	}
	else if (cmp < 0) {
		parent->left = newNode;
	}
	else {
		parent->right = newNode;
	}

	return true;
}

bool bst_find(BST* tree, K key) {
	TreeNode* curr = tree->root;

	while (curr != NULL) {
		int cmp = key - curr->key;
		if (cmp == 0) {
			return true;
		}
		else if (cmp < 0) {
			curr = curr->left;
		}
		else {
			curr = curr->right;
		}
	}
	//不存在
	return false;
}

bool bst_delete(BST* tree, K key) {
	//找到要删除的结点
	TreeNode* parent = NULL;
	TreeNode* curr = tree->root;

	while (curr != NULL) {
		int cmp = key - curr->key;
		if (cmp == 0) {
			break;
		}
		else if (cmp<0	){//往左走
			parent = curr;
			curr = curr->left;
		}
		else {
			parent = curr;
			curr = curr->right;
		}
	}
	
	if (curr == NULL) {
		return false;
	}
	//删除cur指向的节点
	//将度为 degree=2的情况退化成degree=0或者degree=1
	if (curr->left != NULL && curr->right != NULL) {
		//找右子树最小结点
		TreeNode* minParent = curr;
		TreeNode* minOfRight = curr->right;

		while (minOfRight->left != NULL) {
			minParent = minOfRight;
			minOfRight = minOfRight->left;
		}
		//替换值
		curr->key = minParent->key;
		//退化
		parent = minParent;
		curr = minOfRight;
	}

	//处理degree=1和degree=0
	//删除curr指向的结点
	TreeNode* child = curr->left ? curr->left : curr->right;
	if (parent == NULL) {
		tree->root = child;//删除根结点
	}
	else if (curr->key - parent->key < 0) {
		parent->left = child; //将为唯一的子树链接到parent的左边
	}
	else {
		parent->right = child; //将唯一的子树链接到parent的右边
	}

	free(curr);
	return true;
}

 //中序遍历
void inorder(TreeNode* node) {
	if (node == NULL)return;
	//递归公式
	//遍历左子树
	inorder(node->left);
	//遍历根结点
	printf("%c ", node->key);
	//遍历右子树
	inorder(node->right);
}

void bst_inorder(BST* tree) {
	//委托
	inorder(tree->root);
	printf("\n");
}

void bst_levelorder(BST* tree) {
	if (tree->root == NULL)return;

	Queue* q = create_queue();
	//将根节点入队列
	enqueue(q, tree->root);
	//判断队列是否为空
	while (!isEmpty(q)) {
		TreeNode* node = dequeue(q);
		printf("%c", node->key);
		//判断是否有左孩子
		if (node->left != NULL) {
			enqueue(q, node->left);
		}
		//判断是否有右孩子
		if (node->right != NULL) {
			enqueue(q, node->right);
		}
	}
	printf("\n");

	destroy_queue(q);


}

Queue.c

#include "Queue.h"
#include<stdlib.h>
#include<stdio.h>

Queue* create_queue() {
	return calloc(1, sizeof(Queue));
}

void destroy_queue(Queue* q) {
	free(q);
}

bool isEmpty(Queue* q) {
	return q->size == 0;
}

bool isFull(Queue* q) {
	return q->size == N;
}

void enqueue(Queue* q, E val) {
	//判满
	if (isFull(q) ){
		return;
	}
	//添加到队尾
	q->elements[q->rear] = val;
	q->rear = (q->rear + 1) % N;
	q->size++;
}

E dequeue(Queue* q) {
	//判空
	if (isEmpty(q)) {
		printf("Error: empty queue\n");
		exit(1);
	}

	E result = q->elements[q->front];
	q->front = (q->front + 1) % N;
	q->size--;
	return result;
}

E peek(Queue* q) {
	if (isEmpty(q)) {
		printf("Error: empty queue\n");
		exit(1);
	}
	return q->elements[q->front];
}

int size(Queue* q) {
	return q->size;
}

main.c

#include"BST.h"

int main(void) {
	BST* tree = bst_create();//空树

	bst_insert(tree, 'M');              //M
	bst_insert(tree, 'B');        //B           P
	bst_insert(tree, 'P');            //K
	bst_insert(tree, 'K');
	bst_insert(tree, 'B');
	
	/*printf("%s\n", bst_find(tree, 'p') ? "true" : "false");
	printf("%s\n", bst_find(tree, 'x') ? "true" : "false");

	printf("%s\n", bst_delete(tree, 'm') ? "true" : "false");
	printf("%s\n", bst_delete(tree, 'x') ? "true" : "false");*/

	bst_inorder(tree);
	/*bst_levelorder(tree);*/

	return 0;
}

3.平衡二叉搜索树

AVL:任意一个结点,其左子树和右子树高度之差不能超过1。
红黑树:h=log(n)

红黑树

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值