《数据结构(C语言版)第二版》第七章-查找(7.2-7.3.1)

7.2 线性表的查找(适用于静态查找表)

7.2.1 顺序查找

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

#define MAXSIZE 100

typedef int KeyType;
typedef char InfoType;

//数据元素类型定义
typedef struct
{
	KeyType Key;
	InfoType otherinfo;
}ElemType;

//顺序表的定义(线性表的顺序存储结构)
typedef struct
{
	ElemType* R;
	int length;
}SSTable;


void InitSSTable(SSTable& ST);
int Search_Seq(SSTable ST, KeyType key);
int Search_Seq_Key(SSTable ST, KeyType key);


int main()
{
	int i = 0;
	SSTable ST = {NULL,0};
	int m = 0;
	int n = 0;
	
	InitSSTable(ST);

	for (i = 1; i <= 20; i++)
	{
		ST.R[i].Key = i;
	}

	ST.length = 20;

	m = Search_Seq(ST, 15);	
	if (!m)
	{
		printf("查找不成功。");
	}
	else
	{
		printf("15在顺序表ST中的位置数为:%d", m);
	}

	n = Search_Seq_Key(ST, 15);
	if (!n)
	{
		printf("\n使用设置监视哨法,查找不成功。");
	}
	else
	{
		printf("\n使用设置监视哨法,15在顺序表ST中的位置数为:%d", n);
	}

	return 0;
}

//顺序表的初始化
void InitSSTable(SSTable& ST)
{
	ST.R = (ElemType*)malloc(sizeof(ElemType) * MAXSIZE);

	if (!ST.R)
	{
		printf("初始化顺序表失败。\n");
		return;
	}

	ST.length = 0;
}


//算法7.1 顺序查找
int Search_Seq(SSTable ST, KeyType key)
{
	int i = 0;
	for (i = ST.length; i >= 1; i--)
	{
		if (ST.R[i].Key == key)
		{
			return i;
		}
	}

	return 0;
}

//算法7.2 设置监视哨的顺序查找
int Search_Seq_Key(SSTable ST, KeyType key)
{
	int i = 0;
	ST.R[0].Key = key;
	
	for (i = ST.length; ST.R[i].Key != key; --i)
	{
		;
	}

	return i;
}

在这里插入图片描述

7.2.2 折半查找

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

#define MAXSIZE 100

typedef int KeyType;
typedef char InfoType;

//数据元素类型定义
typedef struct
{
	KeyType Key;
	InfoType otherinfo;
}ElemType;

//顺序表的定义(线性表的顺序存储结构)
typedef struct
{
	ElemType* R;
	int length;
}SSTable;


void InitSSTable(SSTable& ST);
int Search_Bin(SSTable ST, KeyType key);
int Search_Bin_Re(SSTable ST, KeyType key, int low, int high);


int main()
{
	int i = 0;
	SSTable ST = {NULL,0};
	int m = 0;
	int n = 0;
	
	InitSSTable(ST);

	for (i = 1; i <= 20; i++)
	{
		ST.R[i].Key = i;
	}

	ST.length = 20;

	m = Search_Bin(ST, 15);
	if (!m)
	{
		printf("查找不成功。");
	}
	else
	{
		printf("15在顺序表ST中的位置数为:%d", m);
	}

	n = Search_Bin_Re(ST, 15,1,ST.length);
	if (!n)
	{
		printf("\n使用折半查找的递归方式,查找不成功。");
	}
	else
	{
		printf("\n使用折半查找的递归方式,15在顺序表ST中的位置数为:%d", n);
	}

	return 0;
}

//顺序表的初始化
void InitSSTable(SSTable& ST)
{
	ST.R = (ElemType*)malloc(sizeof(ElemType) * MAXSIZE);

	if (!ST.R)
	{
		printf("初始化顺序表失败。\n");
		return;
	}

	ST.length = 0;
}


//算法7.3 折半查找(顺序存储且递增有序排列)
int Search_Bin(SSTable ST, KeyType key)
{
	int low = 1;
	int high = ST.length;
	int mid = 0;

	while (low <= high)
	{
		mid = (low + high) / 2;

		if (key == ST.R[mid].Key)
		{
			return mid;
		}
		else if (key < ST.R[mid].Key)
		{
			high = mid - 1;
		}
		else
		{
			low = mid + 1;
		}
	}

	return 0;
}

//折半查找的递归程序
int Search_Bin_Re(SSTable ST, KeyType key,int low,int high)
{
	if (low > high) // 增加一个退出条件
		return 0;

	int	mid = (low + high) / 2;

	if (key == ST.R[mid].Key)
	{
		return mid;
	}
	else if(key < ST.R[mid].Key)
	{
		return Search_Bin_Re(ST, key, low, mid - 1);
	}
	else
	{
		return Search_Bin_Re(ST, key, mid + 1, high);
	}

	return 0;
}

在这里插入图片描述

//折半查找的递归程序写法2【采用上面那一种】

int Search_Bin_Re(SSTable ST, KeyType key, int low, int high)
{
	int mid = 0;

	while (low <= high)
	{
		mid = (low + high) / 2;
		if (key == ST.R[mid].Key)
		{
			return mid;
		}
		else if (key < ST.R[mid].Key)
		{
			return Search_Bin_Re(ST, key, low, mid - 1);
		}
		else
		{
			return Search_Bin_Re(ST, key, mid + 1, high);
		}
	}

	return 0;
}

7.2.3 分块查找(对原始表的要求高)

//定义索引表结构体
typedef struct index
{
	int key;//最大关键字 
	int start;//起始地址 
}Index[b]; 

在这里插入图片描述
(1)划分数据:首先,将含有n个记录的整个数据表,均匀地划分为b个子表(块),每个块包含s个元素。b为不小于n/s的最小整数;

(2)观察块(不对块中的元素进行排序,只寻找块中的最大值和最小值),对块进行排序:使得块与块之间满足“前一个块的最大值小于后一个块的最小值”的要求。可以将块与块进行交换,如果交换之后,也不能满足,那么说明此数据表不能使用分块查找法。
【应直接选择顺序查找,或对整个数据表进行排序后使用折半查找。】

(3)建立索引表:选择每个块中的最大值作为索引表中该块的最大关键字域,并将该块的第一个位置作为索引表中该块的起始地址域值。【因为第二步,所以此时的索引表一定是有序(递增)的。】

(4)在索引表中使用顺序查找或折半查找确定所在块;因为块中记录是任意排列的,所以在块中使用顺序查找确定目标元素的位置。

7.3 树表的查找(适用于动态查找表)

【均只适用于存储在计算机内存中较小的文件中的查找,统称为内查找法。】

7.3.1 二叉排序树

7.3.1.1 二叉排序树的查找(递归与非递归)

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

typedef int KeyType;
typedef char InfoType;

//二叉排序树的二叉链表存储表示
typedef struct
{
	KeyType Key;
	InfoType otherinfo;
}ElemType;

typedef struct BSTNode
{
	ElemType data;
	struct BSTNode* lchild;
	struct BSTNode* rchild;
}BSTNode, * BSTree;

void InitBiTree(BSTree& T);
void CreateBSTree(BSTree& T);
void preOrderTraverse(BSTree T);
void InOrderTraverse(BSTree T);
void posOrderTraverse(BSTree T);
BSTree SearchBST(BSTree T, KeyType key);
BSTree SearchBST_NonRe(BSTree T, KeyType key);

int main()
{
	BSTree T = NULL;
	int k = 0;
	BSTree m = NULL;
	BSTree n = NULL;
	char choice = '\0';

	InitBiTree(T);

	printf("请输入二叉排序树的序列:\n");
	CreateBSTree(T);

	printf("\n二叉排序树链表的先序序列为: ");
	preOrderTraverse(T);

	printf("\n二叉排序树链表的中序序列为: ");
	InOrderTraverse(T);

	printf("\n二叉排序树链表的后序序列为: ");
	posOrderTraverse(T);

	while (1)
	{
		printf("\n请输入要查找的数:");
		scanf_s(" %d", &k);
		m = SearchBST(T, k);
		if (!m)
		{
			printf("使用递归方式进行二叉排序树的查找时,查找%d不成功。", k);
		}
		else
		{
			printf("使用递归方式进行二叉排序树的查找%d时,以其为根结点的树的中序序列为:", k);
			InOrderTraverse(m);
		}


		n = SearchBST_NonRe(T, k);
		if (!n)
		{
			printf("\n使用非递归方式进行二叉排序树的查找时,查找%d不成功。", k);
		}
		else
		{
			printf("\n使用递归方式进行二叉排序树的查找%d时,以其为根结点的树的中序序列为:", k);
			InOrderTraverse(n);
		}

		printf("\n是否继续?(y/n)");
		scanf_s(" %c", &choice);
		getchar();

		if (choice != 'y' && choice != 'Y')
		{
			break;
		}
	}


	return 0;
}


//初始化二叉排序树
void InitBiTree(BSTree& T)
{
	T = NULL;
}


//创建二叉排序树
//输入的二叉排序树的先序序列正确时,输入最后一个结点的关键字域值后,创建程序会自动结束
void CreateBSTree(BSTree& T)
{
	KeyType ch = 0;

	printf("请输入结点的关键字域值(结点不存在时,输入0):");
	scanf_s(" %d", &ch);

	if (ch == 0)
	{
		T = NULL;
	}
	else if (ch != 0)
	{
		T = (BSTree)malloc(sizeof(BSTNode));
		T->data.Key = ch;
		CreateBSTree(T->lchild);
		CreateBSTree(T->rchild);
	}
}


//先序递归遍历二叉排序树
void preOrderTraverse(BSTree T)
{
	if (T)  //只有当T不为空时才访问它的成员
	{
		printf(" %d", T->data.Key);
		preOrderTraverse(T->lchild);
		preOrderTraverse(T->rchild);
	}
}

//中序递归遍历二叉排序树
void InOrderTraverse(BSTree T)
{
	if (T)
	{
		InOrderTraverse(T->lchild);
		printf(" %d", T->data.Key);
		InOrderTraverse(T->rchild);
	}
}

//后序递归遍历二叉排序树
void posOrderTraverse(BSTree T)
{
	if (T)
	{
		posOrderTraverse(T->lchild);
		posOrderTraverse(T->rchild);
		printf(" %d", T->data.Key);
	}
}

//算法7.4 二叉排序树的递归查找
BSTree SearchBST(BSTree T, KeyType key)
{
	if ((!T) || key == T->data.Key)
	{
		return T;
	}
	else if (key < T->data.Key)
	{
		return SearchBST(T->lchild, key);
	}
	else
	{
		return SearchBST(T->rchild, key);
	}
}

//二叉排序树的非递归查找
BSTree SearchBST_NonRe(BSTree T, KeyType key)
{
	BSTree p = T;

	while (p != NULL && p->data.Key != key)
	{
		if (key < p->data.Key)
		{
			p = p->lchild;
		}
		else
		{
			p = p->rchild;
		}
	}

	return p;
}

3, 12, 24 , 37, 45, 53, 61, 78, 90, 100
先根据定义画出任一二叉排序树(满足定义即可),再写出其先序序列,输入程序中即可实现创建该指定二叉树

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

3, 12, 24 , 37, 45, 53, 61, 78, 90, 100
每个递增序列的二叉排序树不唯一;
每个递增序列的二叉排序树的先序序列不唯一;
每个递增序列的二叉排序树的中序序列是唯一,就是其本身。

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

7.3.1.2 二叉排序树的创建

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

#define ENDFLAG -1 //自定义常量,作为输入结束标志

typedef int KeyType;
typedef char InfoType;

//二叉排序树的二叉链表存储表示
typedef struct
{
	KeyType Key;
	InfoType otherinfo;
}ElemType;

typedef struct BSTNode
{
	ElemType data;
	struct BSTNode* lchild;
	struct BSTNode* rchild;
}BSTNode,*BSTree;

void InitBiTree(BSTree& T);
void InsertBST(BSTree& T, ElemType e);
void CreateBST(BSTree& T);
void preOrderTraverse(BSTree T);
void InOrderTraverse(BSTree T);
void posOrderTraverse(BSTree T);

int main()
{
	BSTree T = NULL;

	InitBiTree(T);
	CreateBST(T);

	printf("\n二叉排序树链表的先序序列为: ");
	preOrderTraverse(T);

	printf("\n二叉排序树链表的中序序列为: ");
	InOrderTraverse(T);

	printf("\n二叉排序树链表的后序序列为: ");
	posOrderTraverse(T);

	return 0;
}


//初始化二叉排序树
void InitBiTree(BSTree& T)
{
	T = NULL;
}

//算法 7.5 二叉排序树的插入
//前提:当二叉排序树T中不存在关键字等于e.key的数据元素时, 则插入该元素
void InsertBST(BSTree& T, ElemType e)
{
	if (!T)
	{
		BSTree S = (BSTree)malloc(sizeof(BSTNode));
		S->data = e;
		S->lchild = NULL;
		S->rchild = NULL;
		T = S; //把新结点*S链接到已找到的插入位置
	}
	else if (e.Key < T->data.Key)
	{
		InsertBST(T->lchild, e);
	}
	else if(e.Key > T->data.Key)
	{
		InsertBST(T->rchild, e);
	}
	else
	{
		printf("当二叉排序树T中存在关键字等于%d的结点,无法插入。\n", e.Key);
		return;
	}
}

//算法7.6 二叉排序树的创建(在插入操作的基础上,且是从空的二叉排序树开始的)
//依次读人一个关键字为key的结点, 将此结点插人二叉排序树T中
void CreateBST(BSTree& T)
{
	InitBiTree(T);

	ElemType e = { 0,'\0' };
	printf("请输入新结点的关键字key值:");
	scanf_s(" %d", &e.Key);

	while (e.Key != ENDFLAG)  //ENDFLAG为自定义常量-1,作为输入结束标志
	{
		InsertBST(T, e);
		e = { 0,'\0' };
		printf("请输入新结点的关键字key值:");
		scanf_s(" %d", &e.Key);
	}
}

//先序递归遍历二叉排序树
void preOrderTraverse(BSTree T)
{
	if (T)  //只有当T不为空时才访问它的成员
	{
		printf(" %d", T->data.Key);
		preOrderTraverse(T->lchild);
		preOrderTraverse(T->rchild);
	}
}

//中序递归遍历二叉排序树
void InOrderTraverse(BSTree T)
{
	if (T)
	{
		InOrderTraverse(T->lchild);
		printf(" %d", T->data.Key);
		InOrderTraverse(T->rchild);
	}
}

//后序递归遍历二叉排序树
void posOrderTraverse(BSTree T)
{
	if (T)
	{
		posOrderTraverse(T->lchild);
		posOrderTraverse(T->rchild);
		printf(" %d", T->data.Key);
	}
}
7.3.1.2.1 创建任意的二叉排序树

随机输入序列的每个值,根据运行结果的先序、中序、后序序列,确定构造的二叉排序树具体形态。
【该二叉排序树一定也是符合定义的】

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

一个无序序列可以通过构造一棵二叉排序树而变成一个有序序列, 构造树的过程即为对无序序列进行排序的过程。
无论输入时的序列是何种顺序,CreatBST函数都会返回一个符合二叉排序树定义的正确的二叉排序树。

//算法 7.5 二叉排序树的插入
//前提:当二叉排序树T中不存在关键字等于e.key的数据元素时, 则插入该元素
void InsertBST(BSTree& T, ElemType e)
{
	if (!T)
	{
		BSTree S = (BSTree)malloc(sizeof(BSTNode));
		S->data = e;
		S->lchild = NULL;
		S->rchild = NULL;
		T = S; //把新结点*S链接到已找到的插入位置
		printf("【a】T->data = %d\n", T->data);
	}
	else if (e.Key < T->data.Key)
	{
		printf("【b】T->data = %d\n", T->data);
		InsertBST(T->lchild, e);
	}
	else if (e.Key > T->data.Key)
	{
		printf("【c】T->data = %d\n", T->data);
		InsertBST(T->rchild, e);
	}
	else
	{
		printf("当二叉排序树T中存在关键字等于%d的结点,无法插入。\n", e.Key);
		return;
	}
}

//算法7.6 二叉排序树的创建(在插入操作的基础上,且是从空的二叉排序树开始的)
//依次读人一个关键字为key的结点, 将此结点插人二叉排序树T中
void CreateBST(BSTree& T)
{
	InitBiTree(T);

	ElemType e = { 0,'\0' };
	printf("请输入新结点的关键字key值:");
	scanf_s(" %d", &e.Key);

	while (e.Key != ENDFLAG)  //ENDFLAG为自定义常量-1,作为输入结束标志
	{
		if (T)
		{
			printf("【1】T->data = %d\n", T->data);
		}

		InsertBST(T, e);

		if (T)
		{
			printf("【2】T->data = %d\n", T->data);
		}

		e = { 0,'\0' };
		printf("请输入新结点的关键字key值:");
		scanf_s(" %d", &e.Key);
	}
}

在这里插入图片描述

7.3.1.2.2 创建指定的二叉排序树

3, 12, 24 , 37, 45, 53, 61, 78, 90, 100
先画出想要创建的二叉排序树(必须满足定义),再写出其先序序列,输入程序中即可实现创建该指定二叉树
【此方法比查找中的创建方式输入上更简单】

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

7.3.1.3 二叉排序树的插入

在已创建的非空排序二叉树中插入新结点

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

#define ENDFLAG -1 //自定义常量,作为输入结束标志

typedef int KeyType;
typedef char InfoType;

//二叉排序树的二叉链表存储表示
typedef struct
{
	KeyType Key;
	InfoType otherinfo;
}ElemType;

typedef struct BSTNode
{
	ElemType data;
	struct BSTNode* lchild;
	struct BSTNode* rchild;
}BSTNode, * BSTree;

void InitBiTree(BSTree& T);
int InsertBST(BSTree& T, ElemType e);
void CreateBST(BSTree& T);
void preOrderTraverse(BSTree T);
void InOrderTraverse(BSTree T);
void posOrderTraverse(BSTree T);

int main()
{
	BSTree T = NULL;
	int key = 0;
	ElemType e = { 0,'\0' };
	int r = 0;
	char choice = '\0';

	InitBiTree(T);
	CreateBST(T);

	printf("\n二叉排序树链表的先序序列为: ");
	preOrderTraverse(T);

	printf("\n二叉排序树链表的中序序列为: ");
	InOrderTraverse(T);

	printf("\n二叉排序树链表的后序序列为: ");
	posOrderTraverse(T);


	//在已创建的非空排序二叉树中插入新结点
	while (1)
	{
		printf("\n请输入要插入的新结点的关键字值:");
		scanf_s(" %d", &key);
		e.Key = key;
		r = InsertBST(T, e);

		if (r)
		{
			printf("\n新二叉排序树链表的先序序列为: ");
			preOrderTraverse(T);

			printf("\n新二叉排序树链表的中序序列为: ");
			InOrderTraverse(T);

			printf("\n新二叉排序树链表的后序序列为: ");
			posOrderTraverse(T);
		}


		printf("\n是否继续?(y/n)");
		scanf_s(" %c", &choice);
		getchar();

		if (choice != 'y' && choice != 'Y')
		{
			break;
		}
	}

	return 0;
}


//初始化二叉排序树
void InitBiTree(BSTree& T)
{
	T = NULL;
}

//算法 7.5 二叉排序树的插入
//前提:当二叉排序树T中不存在关键字等于e.key的数据元素时, 则插入该元素
int InsertBST(BSTree& T, ElemType e)
{
	if (!T)
	{
		BSTree S = (BSTree)malloc(sizeof(BSTNode));
		S->data = e;
		S->lchild = NULL;
		S->rchild = NULL;
		T = S; //把新结点*S链接到已找到的插入位置
		return 1;
	}
	else if (e.Key < T->data.Key)
	{
		return InsertBST(T->lchild, e);
	}
	else if (e.Key > T->data.Key)
	{
		return InsertBST(T->rchild, e);
	}
	else
	{
		printf("当二叉排序树T中存在关键字等于%d的结点,无法插入。\n", e.Key);
		return 0;
	}
}

//算法7.6 二叉排序树的创建(在插入操作的基础上,且是从空的二叉排序树开始的)
//依次读人一个关键字为key的结点, 将此结点插人二叉排序树T中
void CreateBST(BSTree& T)
{
	InitBiTree(T);

	ElemType e = { 0,'\0' };
	printf("请输入新结点的关键字key值:");
	scanf_s(" %d", &e.Key);

	while (e.Key != ENDFLAG)  //ENDFLAG为自定义常量-1,作为输入结束标志
	{
		InsertBST(T, e);
		e = { 0,'\0' };
		printf("请输入新结点的关键字key值:");
		scanf_s(" %d", &e.Key);
	}
}

//先序递归遍历二叉排序树
void preOrderTraverse(BSTree T)
{
	if (T)  //只有当T不为空时才访问它的成员
	{
		printf(" %d", T->data.Key);
		preOrderTraverse(T->lchild);
		preOrderTraverse(T->rchild);
	}
}

//中序递归遍历二叉排序树
void InOrderTraverse(BSTree T)
{
	if (T)
	{
		InOrderTraverse(T->lchild);
		printf(" %d", T->data.Key);
		InOrderTraverse(T->rchild);
	}
}

//后序递归遍历二叉排序树
void posOrderTraverse(BSTree T)
{
	if (T)
	{
		posOrderTraverse(T->lchild);
		posOrderTraverse(T->rchild);
		printf(" %d", T->data.Key);
	}
}

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

在这里插入图片描述

在这里插入图片描述

7.3.1.4 二叉排序树的删除

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

#define ENDFLAG -1 //自定义常量,作为输入结束标志

typedef int KeyType;
typedef char InfoType;

//二叉排序树的二叉链表存储表示
typedef struct
{
	KeyType Key;
	InfoType otherinfo;
}ElemType;

typedef struct BSTNode
{
	ElemType data;
	struct BSTNode* lchild;
	struct BSTNode* rchild;
}BSTNode, * BSTree;

void InitBiTree(BSTree& T);
void InsertBST(BSTree& T, ElemType e);
void CreateBST(BSTree& T);
void preOrderTraverse(BSTree T);
void InOrderTraverse(BSTree T);
void posOrderTraverse(BSTree T);
void DeleteBST(BSTree& T, KeyType key);

int main()
{
	BSTree T = NULL;
	KeyType k = 0;

	InitBiTree(T);
	CreateBST(T);

	printf("\n二叉排序树链表的先序序列为: ");
	preOrderTraverse(T);

	printf("\n二叉排序树链表的中序序列为: ");
	InOrderTraverse(T);

	printf("\n二叉排序树链表的后序序列为: ");
	posOrderTraverse(T);

	printf("\n\n请输入要删除的结点关键字值:");
	scanf_s(" %d", &k);
	DeleteBST(T, k);

	printf("\n\n删除%d后,二叉排序树链表的先序序列为:", k);
	preOrderTraverse(T);

	printf("\n删除%d后,二叉排序树链表的中序序列为:", k);
	InOrderTraverse(T);

	printf("\n删除%d后,二叉排序树链表的后序序列为:", k);
	posOrderTraverse(T);
	return 0;
}


//初始化二叉排序树
void InitBiTree(BSTree& T)
{
	T = NULL;
}

//算法 7.5 二叉排序树的插入
//前提:当二叉排序树T中不存在关键字等于e.key的数据元素时, 则插入该元素
void InsertBST(BSTree& T, ElemType e)
{
	if (!T)
	{
		BSTree S = (BSTree)malloc(sizeof(BSTNode));
		S->data = e;
		S->lchild = NULL;
		S->rchild = NULL;
		T = S; //把新结点*S链接到已找到的插入位置
	}
	else if (e.Key < T->data.Key)
	{
		InsertBST(T->lchild, e);
	}
	else if (e.Key > T->data.Key)
	{
		InsertBST(T->rchild, e);
	}
	else
	{
		printf("当二叉排序树T中存在关键字等于%d的结点,无法插入。\n", e.Key);
		return;
	}
}

//算法7.6 二叉排序树的创建(在插入操作的基础上,且是从空的二叉排序树开始的)
//依次读人一个关键字为key的结点, 将此结点插人二叉排序树T中
void CreateBST(BSTree& T)
{
	InitBiTree(T);

	ElemType e = { 0,'\0' };
	printf("请输入新结点的关键字key值:");
	scanf_s(" %d", &e.Key);

	while (e.Key != ENDFLAG)  //ENDFLAG为自定义常量-1,作为输入结束标志
	{
		InsertBST(T, e);
		e = { 0,'\0' };
		printf("请输入新结点的关键字key值:");
		scanf_s(" %d", &e.Key);
	}
}

//先序递归遍历二叉排序树
void preOrderTraverse(BSTree T)
{
	if (T)  //只有当T不为空时才访问它的成员
	{
		printf(" %d", T->data.Key);
		preOrderTraverse(T->lchild);
		preOrderTraverse(T->rchild);
	}
}

//中序递归遍历二叉排序树
void InOrderTraverse(BSTree T)
{
	if (T)
	{
		InOrderTraverse(T->lchild);
		printf(" %d", T->data.Key);
		InOrderTraverse(T->rchild);
	}
}

//后序递归遍历二叉排序树
void posOrderTraverse(BSTree T)
{
	if (T)
	{
		posOrderTraverse(T->lchild);
		posOrderTraverse(T->rchild);
		printf(" %d", T->data.Key);
	}
}


//算法 7.7 二叉排序树的删除
void DeleteBST(BSTree& T, KeyType key)
{
	BSTree p = T;
	BSTree f = NULL;
	BSTree q = NULL;
	BSTree s = NULL;

	//下面的 while循环从根开始查找关键字等于 key的结点*p
	while (p)
	{
		if (p->data.Key == key)
		{
			break;
		}

		f = p;

		if (p->data.Key > key)
		{
			p = p->lchild;
		}
		else
		{
			p = p->rchild;
		}
	}

	if (!p)
	{
		printf("查找关键字值为%d的结点失败。\n", key);
		return;
	}

	//考虑3种情况实现p所指子树内部的处理: *p左右子树均不空、 无右子树、 无左子树
	if (p->lchild && p->rchild)
	{
		q = p;
		s = p->lchild;

		while (s->rchild)
		{
			q = s;
			s = s->rchild;
		}

		p->data = s->data;

		if (q != p)
		{
			q->rchild = s->lchild;
		}
		else
		{
			q->lchild = s->lchild;
		}

		free(s);
		s = NULL;
		return;  //退出整个函数,不会受后面释放q的影响
	}
	else if (!p->rchild)
	{
		q = p;
		p = p->lchild;
	}
	else if (!p->lchild)
	{
		q = p;
		p = p->rchild;
	}

	//针对后面两种情况
	if (!f)
	{
		T = p;  //如果删除的是根节点,更新根节点(在目标结点左右子树均非空的情况下,不需要更新)
	}
	else if (q == f->lchild)  	//将 p 所指的子树挂接到其双亲结点*f相应的位置
	{
		f->lchild = p;
	}
	else  //if (q == f->rchild)
	{
		f->rchild = p;
	}

	free(q);  //在目标结点左右子树均非空的情况下不能释放q,此时已经退出整个函数
	q = NULL;
}

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

7.3.2 平衡二叉树

全网最清晰快速排序,看完快排思想和代码全部通透,不通透你打我!—— 公台所言极是

讲解平衡二叉树的实现(C语言)—— 尘封的时间

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值