如何使用C语言实现平衡二叉树数据结构算法

目录
  • 前言
  • 一、平衡二叉树实现原理
  • 二、平衡二叉树实现算法
  • 三、全部代码

前言

对于一个二叉排序树而言

  • 它们的结构都是根据了二叉树的特性从最左子树开始在回到该结点上继续往右结点走
  • 通过该方式进行递归操作,并且该二叉排序树的结构也是从小到大依次显示
  • 那么我们假设a[10]={ 3,2,1,4,5,6,7,10,9,8 };我们需要查找改列表中的某一个结点的值

那么我们通过二叉排序树的展示,会展示成如图:

可以发现,如果我们想通过二叉排序树这个深度为8的树来查找某个数

我们需要走到最后,这是最坏的打算

但是如果我们能将该树改变为平衡二叉树,如图所示:

相比之下我们这个深度为4的平衡二叉树在通过查询值时是效率很平均且稳定的,

那么通过上面的问题我们该怎么将这个二叉排序树的变成平衡二叉树是我们现在的问题了。

一、平衡二叉树实现原理

对于平衡二叉树的特性而言,我们在上面也有举例到

  • 在二叉排序树中,按照它的从小到大的结构所排序下来的结点,
  • 当它的平衡因子的绝对值大于1的结点的根的子树,我们称为最小不平衡子树。

而我们该如何去计算该二叉排序树的平衡因子(平衡因子 = 左子树 - 右子树的值)呢?

我们可以结合上面那个最坏打算的二叉排序树的生成方式进行逐一分析。

如图:

可以看到当我们单步调试二叉排序树的时候到值1的时候值3的平衡因子为2>1

  • (左子树有值2、值1所以是2-右子树0所以等于2)

那么此时并不符合我们的平衡二叉树的规则

那么我们需要通过某种形式去调换,使其符合我们的平衡二叉树的规则

而图2就是由图1通过顺时针而得到出来的,在这里我们称为右旋

  • 此时我们所有的平衡因子<2那么又恢复了正常

之后我们的值4继续插入,因为值4>值3,所以根据二叉排序树的特性是值3的右子树

  • 此时我们查看图3发现所有的平衡因子<2,

那么也没出现什么问题之后继续插入下一个值5,因为值5>值4,所以值5会到值4的右子树上。

如图所示:

可以发现图4中当插入值5的时候,根节点、值3的平衡因子的绝对值=2

  • 所以是不符合平衡条件的所以此时我们通过逆时针的方式去旋转值3下面的所有结点
  • 在这里我们称为左旋,得到的结果即为图5所示了,且此时每个结点的平衡因子都<2,恢复平衡了

剩下就不多去演示了,整体是一个递归的过程

重要:在过程中反复的把不平衡的结点通过左、右旋的方式将其调整回平衡二叉树。

要想深刻了解平衡二叉树的实现原理请自行参考程杰著作的《大话数据结构》。

二、平衡二叉树实现算法

在类型上我们会通过二叉排序树的基础上添加一个bf,用于存储平衡因子,而定义了一个Status则是判断当前状态的代码。

代码如下:

typedef int Status;	/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
/* 二叉树的二叉链表结点结构定义 */
typedef  struct BiTNode	/* 结点结构 */
{
	int data;	/* 结点数据 */
	int bf; /*  结点的平衡因子 */
	struct BiTNode* lchild, * rchild;	/* 左右孩子指针 */
} BiTNode, * BiTree;

为了方便理解,我们前面的提到的左旋和右旋的方式,在c语言的代码中该如何实现呢?下面我们就来将代码展示出来。

代码如下:

void R_Rotate(BiTree* P)
{
	BiTree L;
	L = (*P)->lchild; /*  L指向P的左子树根结点 */
	(*P)->lchild = L->rchild; /*  L的右子树挂接为P的左子树 */
	L->rchild = (*P);
	*P = L; /*  P指向新的根结点 */
}
/* 对以P为根的二叉排序树作左旋处理, */
/* 处理之后P指向新的树根结点,即旋转处理之前的右子树的根结点0  */
void L_Rotate(BiTree* P)
{
	BiTree R;
	R = (*P)->rchild; /*  R指向P的右子树根结点 */
	(*P)->rchild = R->lchild; /* R的左子树挂接为P的右子树 */
	R->lchild = (*P);
	*P = R; /*  P指向新的根结点 */
}

我们可以看到左旋和右旋的代码很类似,所以我们通过了解了右旋的代码的含义自然就可以反推出左旋的含义了。

此函数的意思是:

  • 当某一个结点P处于一个不平衡状态的时候,且平衡因子为正数需要右旋(顺时针),并将它的左孩子结点定义为L。
  • 将L的右子树变成P的左子树,再将P改成L的右子树,最后将L替换P成功根结点。

如果文字还不了解我们可以将上述图1、图2的图片进行推导。

如图:

那么左旋的操作就是一个逆时针的方向转换,代码也是类似这里就不再演示了。

  • 但是在这里我们还有另一种情况,就是当有两个或以上的平衡因子的绝对值>=2的时候,它们的平衡因子的值可能为负也可能为正,那么这种情况我们就要考虑到双旋操作了,
  • 我们假设以树根为顶点的左右子树都需要考虑,且它们是相对的,所以我们可以通过了解左平衡旋转处理也就继而反推出右平衡旋转处理了。

现在我们来看左平衡旋转处理的代码函数:

#define LH +1 /*  左高 */
#define EH 0  /*  等高 */
#define RH -1 /*  右高 */
/*  对以指针T所指结点为根的二叉树作右平衡旋转处理, */
/*  本算法结束时,指针T指向新的根结点 */
void RightBalance(BiTree* T)
{
	BiTree R, Rl;
	R = (*T)->rchild; /*  R指向T的右子树根结点 */
	switch (R->bf)
	{ /*  检查T的右子树的平衡度,并作相应平衡处理 */
	case RH: /*  新结点插入在T的右孩子的右子树上,要作单左旋处理 */
		(*T)->bf = R->bf = EH;
		L_Rotate(T);
		break;
	case LH: /*  新结点插入在T的右孩子的左子树上,要作双旋处理 */
		Rl = R->lchild; /*  Rl指向T的右孩子的左子树根 */
		switch (Rl->bf)
		{ /*  修改T及其右孩子的平衡因子 */
		case RH: (*T)->bf = LH;
			R->bf = EH;
			break;
		case EH: (*T)->bf = R->bf = EH;
			break;
		case LH: (*T)->bf = EH;
			R->bf = RH;
			break;
		}
		Rl->bf = EH;
		R_Rotate(&(*T)->rchild); /*  对T的右子树作右旋平衡处理 */
		L_Rotate(T); /*  对T作左旋平衡处理 */
	}
}
/*  对以指针T所指结点为根的二叉树作左平衡旋转处理 */
/*  本算法结束时,指针T指向新的根结点 */
void LeftBalance(BiTree* T)
{
	BiTree L, Lr;
	L = (*T)->lchild; /*  L指向T的左子树根结点 */
	switch (L->bf)
	{ /*  检查T的左子树的平衡度,并作相应平衡处理 */
	case LH: /*  新结点插入在T的左孩子的左子树上,要作单右旋处理 */
		(*T)->bf = L->bf = EH;
		R_Rotate(T);
		break;
	case RH: /*  新结点插入在T的左孩子的右子树上,要作双旋处理 */
		Lr = L->rchild; /*  Lr指向T的左孩子的右子树根 */
		switch (Lr->bf)
		{ /*  修改T及其左孩子的平衡因子 */
		case LH: (*T)->bf = RH;
			L->bf = EH;
			break;
		case EH: (*T)->bf = L->bf = EH;
			break;
		case RH: (*T)->bf = EH;
			L->bf = LH;
			break;
		}
		Lr->bf = EH;
		L_Rotate(&(*T)->lchild); /*  对T的左子树作左旋平衡处理 */
		R_Rotate(T); /*  对T作右旋平衡处理 */
	}
}

如图:

首先通过代码可以看到,我们定义了三个常数变量,分别代码1、0、-1。

然后呢因为是左平衡旋转处理我们需要获取当前图片所示的P结点(也就是我之前假设的根节点的顶点)的左子树,

这里要注意重点:

  • 当我们这个函数可以执行的时候已经确认了当前子树是不平衡的状态;
  • 且结点N的值(即新插入结点) < 结点P的值(即上述图片根结点P)和结点P->左子树高于结点P->右子树需要调整;
  • 并且你还要记住此时进来的结点P才是不平衡状态,且通过该P结点->左子树的平衡因子来进行分支判断。
  1. 如果等于1了则执行一次右旋操作,即上图右旋推导的并且把它们的BF值(平衡因子)都改为0操作;
  2. 反之如果等于-1了则像上图一样进行双旋操作;
  3. 不过在那之前还要通过获取图2上L的右子树LR(贴合代码上的Lr);
  4. 然后再判断一下Lr的平衡因子的值并再次进行分支判断;
  5. 修改根节点P(即代码中的根节点T)根据Lr的BF值进行修改它们的BF值;
  6. 最后在将Lr的BF值赋为0,进行双旋操作这里先左旋后右旋;
  7. 那么右平衡旋转处理函数则取反。

三、全部代码

#include "stdio.h"
#include "stdlib.h"
#include "io.h"
#include "math.h"
#include "time.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100 /* 存储空间初始分配量 */
typedef int Status;	/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
/* 二叉树的二叉链表结点结构定义 */
typedef  struct BiTNode	/* 结点结构 */
{
	int data;	/* 结点数据 */
	int bf; /*  结点的平衡因子 */
	struct BiTNode* lchild, * rchild;	/* 左右孩子指针 */
} BiTNode, * BiTree;
/* 对以p为根的二叉排序树作右旋处理, */
/* 处理之后p指向新的树根结点,即旋转处理之前的左子树的根结点 */
void R_Rotate(BiTree* P)
{
	BiTree L;
	L = (*P)->lchild; /*  L指向P的左子树根结点 */
	(*P)->lchild = L->rchild; /*  L的右子树挂接为P的左子树 */
	L->rchild = (*P);
	*P = L; /*  P指向新的根结点 */
}

/* 对以P为根的二叉排序树作左旋处理, */
/* 处理之后P指向新的树根结点,即旋转处理之前的右子树的根结点0  */
void L_Rotate(BiTree* P)
{
	BiTree R;
	R = (*P)->rchild; /*  R指向P的右子树根结点 */
	(*P)->rchild = R->lchild; /* R的左子树挂接为P的右子树 */
	R->lchild = (*P);
	*P = R; /*  P指向新的根结点 */
}
#define LH +1 /*  左高 */
#define EH 0  /*  等高 */
#define RH -1 /*  右高 */
/*  对以指针T所指结点为根的二叉树作左平衡旋转处理 */
/*  本算法结束时,指针T指向新的根结点 */
void LeftBalance(BiTree* T)
{
	BiTree L, Lr;
	L = (*T)->lchild; /*  L指向T的左子树根结点 */
	switch (L->bf)
	{ /*  检查T的左子树的平衡度,并作相应平衡处理 */
	case LH: /*  新结点插入在T的左孩子的左子树上,要作单右旋处理 */
		(*T)->bf = L->bf = EH;
		R_Rotate(T);
		break;
	case RH: /*  新结点插入在T的左孩子的右子树上,要作双旋处理 */
		Lr = L->rchild; /*  Lr指向T的左孩子的右子树根 */
		switch (Lr->bf)
		{ /*  修改T及其左孩子的平衡因子 */
		case LH: (*T)->bf = RH;
			L->bf = EH;
			break;
		case EH: (*T)->bf = L->bf = EH;
			break;
		case RH: (*T)->bf = EH;
			L->bf = LH;
			break;
		}
		Lr->bf = EH;
		L_Rotate(&(*T)->lchild); /*  对T的左子树作左旋平衡处理 */
		R_Rotate(T); /*  对T作右旋平衡处理 */
	}
}
/*  对以指针T所指结点为根的二叉树作右平衡旋转处理, */
/*  本算法结束时,指针T指向新的根结点 */
void RightBalance(BiTree* T)
{
	BiTree R, Rl;
	R = (*T)->rchild; /*  R指向T的右子树根结点 */
	switch (R->bf)
	{ /*  检查T的右子树的平衡度,并作相应平衡处理 */
	case RH: /*  新结点插入在T的右孩子的右子树上,要作单左旋处理 */
		(*T)->bf = R->bf = EH;
		L_Rotate(T);
		break;
	case LH: /*  新结点插入在T的右孩子的左子树上,要作双旋处理 */
		Rl = R->lchild; /*  Rl指向T的右孩子的左子树根 */
		switch (Rl->bf)
		{ /*  修改T及其右孩子的平衡因子 */
		case RH: (*T)->bf = LH;
			R->bf = EH;
			break;
		case EH: (*T)->bf = R->bf = EH;
			break;
		case LH: (*T)->bf = EH;
			R->bf = RH;
			break;
		}
		Rl->bf = EH;
		R_Rotate(&(*T)->rchild); /*  对T的右子树作右旋平衡处理 */
		L_Rotate(T); /*  对T作左旋平衡处理 */
	}
}
/*  若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个 */
/*  数据元素为e的新结点,并返回1,否则返回0。若因插入而使二叉排序树 */
/*  失去平衡,则作平衡旋转处理,布尔变量taller反映T长高与否。 */
Status InsertAVL(BiTree* T, int e, Status* taller)
{
	if (!*T)
	{ /*  插入新结点,树“长高”,置taller为TRUE */
		*T = (BiTree)malloc(sizeof(BiTNode));
		(*T)->data = e; (*T)->lchild = (*T)->rchild = NULL; (*T)->bf = EH;
		*taller = TRUE;
	}
	else
	{
		if (e == (*T)->data)
		{ /*  树中已存在和e有相同关键字的结点则不再插入 */
			*taller = FALSE; return FALSE;
		}
		if (e < (*T)->data)
		{ /*  应继续在T的左子树中进行搜索 */
			if (!InsertAVL(&(*T)->lchild, e, taller)) /*  未插入 */
				return FALSE;
			if (*taller) /*   已插入到T的左子树中且左子树“长高” */
				switch ((*T)->bf) /*  检查T的平衡度 */
				{
				case LH: /*  原本左子树比右子树高,需要作左平衡处理 */
					LeftBalance(T);	*taller = FALSE; break;
				case EH: /*  原本左、右子树等高,现因左子树增高而使树增高 */
					(*T)->bf = LH; *taller = TRUE; break;
				case RH: /*  原本右子树比左子树高,现左、右子树等高 */
					(*T)->bf = EH; *taller = FALSE; break;
				}
		}
		else
		{ /*  应继续在T的右子树中进行搜索 */
			if (!InsertAVL(&(*T)->rchild, e, taller)) /*  未插入 */
				return FALSE;
			if (*taller) /*  已插入到T的右子树且右子树“长高” */
				switch ((*T)->bf) /*  检查T的平衡度 */
				{
				case LH: /*  原本左子树比右子树高,现左、右子树等高 */
					(*T)->bf = EH; *taller = FALSE;	break;
				case EH: /*  原本左、右子树等高,现因右子树增高而使树增高  */
					(*T)->bf = RH; *taller = TRUE; break;
				case RH: /*  原本右子树比左子树高,需要作右平衡处理 */
					RightBalance(T); *taller = FALSE; break;
				}
		}
	}
	return TRUE;
}
int main(void)
{
	int i;
	int a[10] = { 3,2,1,4,5,6,7,10,9,8 };
	BiTree T = NULL;
	Status taller;
	for (i = 0; i < 10; i++)
	{
		InsertAVL(&T, a[i], &taller);
	}
	printf("本样例建议断点跟踪查看平衡二叉树结构");
	return 0;
}

到此这篇关于如何使用C语言实现平衡二叉树 的文章就介绍到这了,更多相关C语言实现平衡二叉树内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 平衡二叉树的实现实例

    复制代码 代码如下: /*首先平衡二叉树是一个二叉排序树:其基本思想是:在构建二叉排序树的过程中,当每插入一个节点时,先检查是否因为插入而破坏了树的平衡性,若是,找出最小不平衡树,进行适应的旋转,使之成为新的平衡二叉树.*/#include<cstdio>#include<cstdlib>#define LH 1#define EH 0#define RH -1 using namespace std; typedef struct BTNode{ int data; int BF

  • C语言 数据结构平衡二叉树实例详解

    数据结构平衡二叉树 参考代码如下: /* 名称:平衡二叉树 语言:数据结构C语言版 编译环境:VC++ 6.0 日期: 2014-3-26 */ #include <stdio.h> #include <malloc.h> #include <windows.h> #define LH +1 // 左高 #define EH 0 // 等高 #define RH -1 // 右高 #define N 5 // 数据元素个数 typedef char KeyType; /

  • C语言数据结构之平衡二叉树(AVL树)实现方法示例

    本文实例讲述了C语言数据结构之平衡二叉树(AVL树)实现方法.分享给大家供大家参考,具体如下: AVL树是每个结点的左子树和右子树的高度最多差1的二叉查找树. 要维持这个树,必须在插入和删除的时候都检测是否出现破坏树结构的情况.然后立刻进行调整. 看了好久,网上各种各种的AVL树,千奇百怪. 关键是要理解插入的时候旋转的概念. // // AvlTree.h // HelloWorld // Created by feiyin001 on 17/1/9. // Copyright (c) 201

  • 举例讲解C语言程序中对二叉树数据结构的各种遍历方式

    二叉树遍历的基本思想 二叉树的遍历本质上其实就是入栈出栈的问题,递归算法简单且容易理解,但是效率始终是个问题.非递归算法可以清楚的知道每步实现的细节,但是乍一看不想递归算法那么好理解,各有各的好处吧.接下来根据下图讲讲树的遍历. 1.先序遍历:先序遍历是先输出根节点,再输出左子树,最后输出右子树.上图的先序遍历结果就是:ABCDEF 2.中序遍历:中序遍历是先输出左子树,再输出根节点,最后输出右子树.上图的中序遍历结果就是:CBDAEF 3.后序遍历:后序遍历是先输出左子树,再输出右子树,最后输

  • 平衡二叉树AVL操作模板

    复制代码 代码如下: /*** 目的:实现AVL* 利用数组对左右儿子简化代码,但是对脑力难度反而增大不少,只适合acm模板* 其实avl在acm中基本不用,基本被treap取代* avl一般只要求理解思路,不要求写出代码,因为真心很烦*/ #include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <string>#include <

  • 如何使用C语言实现平衡二叉树数据结构算法

    目录 前言 一.平衡二叉树实现原理 二.平衡二叉树实现算法 三.全部代码 前言 对于一个二叉排序树而言 它们的结构都是根据了二叉树的特性从最左子树开始在回到该结点上继续往右结点走 通过该方式进行递归操作,并且该二叉排序树的结构也是从小到大依次显示 那么我们假设a[10]={ 3,2,1,4,5,6,7,10,9,8 };我们需要查找改列表中的某一个结点的值 那么我们通过二叉排序树的展示,会展示成如图: 可以发现,如果我们想通过二叉排序树这个深度为8的树来查找某个数 我们需要走到最后,这是最坏的打

  • C语言数据结构算法之实现快速傅立叶变换

    C语言数据结构算法之实现快速傅立叶变换 本实例将实现二维快速傅立叶变换,同时也将借此实例学习用c语言实现矩阵的基本操作.复数的基本掾作,复习所学过的动态内存分配.文件操作.结构指针的函数调用等内容. 很久以来,傅立叶变换一直是许多领域,如线性系统.光学.概率论.量子物理.天线.数字图像处理和信号分析等的一个基本分析工具,但是即便使用计算速度惊人的计算机计算离散傅立叶变换所花费的时间也常常是难以接受的,因此导致了快速傅立叶变换(FFT)的产生. 本实例将对一个二维数组进行正.反快速傅立叶变换.正傅

  • C语言详解数据结构与算法中枚举和模拟及排序

    目录 枚举 连号区间数 递增三元组 二分 双指针 前缀和 模拟 特别数的和 错误票据 排序 快速排序 归并排序 枚举 连号区间数 来源:第四届蓝桥杯省赛C++B组,第四届蓝桥杯省赛JAVAB组 小明这些天一直在思考这样一个奇怪而有趣的问题: 在 1∼N 的某个排列中有多少个连号区间呢? 这里所说的连号区间的定义是: 如果区间 [L,R] 里的所有元素(即此排列的第 L 个到第 R 个元素)递增排序后能得到一个长度为 R−L+1 的“连续”数列,则称这个区间连号区间. 当 N 很小的时候,小明可以

  • C语言植物大战数据结构希尔排序算法

    目录 前言 一.插入排序 1.排序思路 2.单趟排序 详细图解 3.整体代码 4.时间复杂度 (1).最坏情况下 (2).最好情况下 (3).基本有序情况下(重点) 5.算法特点 二.希尔排序 1.希尔从哪个方面优化的插入排序? 2.排序思路 3.预排序 4.正式排序 5.整体代码 6.时间复杂度 (1).while循环的复杂度 (2).每组gap的时间复杂度 结论: “至若春和景明,波澜不惊,上下天光,一碧万顷,沙鸥翔集,锦鳞游泳,岸芷汀兰,郁郁青青.” C语言朱武大战数据结构专栏 C语言植物

  • C语言数据结构算法基础之循环队列示例

    目录 说明 示例代码 1. 首先定义结构体: 2. 定义各种算法: 3. 测试: 4. 最后的结果: 说明 循环队列是一种先进先出的,首尾相连的队列. 大致的结构如下图: 用数组来抽象的表示一下的话,如下图: 循环队列有两个指针指向数据,上图中的start和end就是那两个指针,它们指向相同的位置,表示的是空,即队列是空的. 随着数据的放入,队列一般有下面的两种形式: 需要注意第二种形式,从图上看end在start的前面了,但是因为循环关系,前后并不重要. 另外需要考虑的是队列满的情况: 但这种

  • Go语言实现Snowflake雪花算法

    每次放长假的在家里的时候,总想找点简单的例子来看看实现原理,这次我们来看看 Go 语言雪花算法. 介绍 有时候在业务中,需要使用一些唯一的ID,来记录我们某个数据的标识.最常用的无非以下几种:UUID.数据库自增主键.Redis的Incr命令等方法来获取一个唯一的值.下面我们分别说一下它们的优劣,以便引出我们的分布式雪花算法. 雪花算法 雪花算法的原始版本是scala版,用于生成分布式ID(纯数字,时间顺序),订单编号等. 自增ID:对于数据敏感场景不宜使用,且不适合于分布式场景. GUID:采

  • C语言实现各种排序算法实例代码(选择,冒泡,插入,归并,希尔,快排,堆排序,计数)

    目录 前言 选择排序 冒泡排序 插入排序 归并排序 希尔排序 快速排序 堆排序 计数排序 总结 前言 平时用惯了高级语言高级工具高级算法,难免对一些基础算法感到生疏.但最基础的排序算法中实则蕴含着相当丰富的优化思维,熟练运用可起到举一反三之功效. 选择排序 选择排序几乎是最无脑的一种排序算法,通过遍历一次数组,选出其中最大(小)的值放在新数组的第一位:再从数组中剩下的数里选出最大(小)的,放到第二位,依次类推. 算法步骤 设数组有n个元素,{ a 0 , a 1 , - , a n } 从数组第

  • C语言 超详细讲解算法的时间复杂度和空间复杂度

    目录 1.前言 1.1 什么是数据结构? 1.2 什么是算法? 2.算法效率 2.1 如何衡量一个算法的好坏 2.2 算法的复杂度 2.3 复杂度在校招中的考察 3.时间复杂度 3.1 时间复杂度的概念 3.2 大O的渐进表示法 3.3 常见时间复杂度计算举例 4.空间复杂度 5. 常见复杂度对比 1.前言 1.1 什么是数据结构? 数据结构(Data Structure)是计算机存储.组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合. 1.2 什么是算法? 算法(Algorit

  • C语言植物大战数据结构二叉树递归

    目录 前言 一.二叉树的遍历算法 1.构造二叉树 2.前序遍历(递归图是重点.) 3.中序遍历 4.后序遍历 二.二叉树遍历算法的应用 1.求节点个数 3.求第k层节点个数 4.查找值为x的节点 5.二叉树销毁 6.前序遍历构建二叉树 7.判断二叉树是否是完全二叉树 8.求二叉树的深度 三.二叉树LeetCode题目 1.单值二叉树 2. 检查两颗树是否相同 3. 对称二叉树 4.另一颗树的子树 6.反转二叉树 " 梧桐更兼细雨,到黄昏.点点滴滴." C语言朱武大战数据结构专栏 C语言

  • C语言植物大战数据结构快速排序图文示例

    目录 快速排序 一.经典1962年Hoare法 1.单趟排序 2.递归左半区间和右半区间 3.代码实现 二.填坑法(了解) 1.单趟思路 2.代码实现 三.双指针法(最佳方法) 1.单趟排序 2.具体思路 3.代码递归图 4.代码实现 四.三数取中优化(最终方案) 1.三数取中 2.代码实现(最终代码) 五.时间复杂度(重点) 1.最好情况下 2.最坏情况下 3.空间复杂度 六.非递归写法 1.栈模拟递归快排 2.队列实现快排 浅浅总结下 “田家少闲月,五月人倍忙”“夜来南风起,小麦覆陇黄” C

随机推荐