第六周day4

二叉树

    链式存储:由一个个节点组成,每个节点都是一个树

        节点数据项:

        数据项:

        左子树指针:

        右子树指针:

    ABDG##H###CEI###F#J##

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

#define TREE_TYPE char
#define EMPTY '#'
#define END '\0'

typedef struct TreeNode
{
	TREE_TYPE data;
	struct TreeNode* left;
	struct TreeNode* right;
}TreeNode;

//创建节点
TreeNode* creat_tree_node(TREE_TYPE data)
{
	TreeNode* node=malloc(sizeof(TreeNode));
	node->left=NULL;
	node->right=NULL;
	node->data=data;
	return node;
}

//构建一棵树 前序

/*
TreeNode* creat_tree(void)
{
	TREE_TYPE data=0;
	scanf("%c",&data);
	if(EMPTY == data) return NULL;
	TreeNode* node = creat_tree_node(data);
	node->left=creat_tree();
	node->right=creat_tree();
	return node;
}
*/

TreeNode* _creat_tree(char** str)
{
	if(EMPTY == **str || END == **str) return NULL;
	TreeNode* node=creat_tree_node(**str);
	*str+=1;
	node->left=_creat_tree(str);
	*str+=1;
	node->right=_creat_tree(str);
	return node;
}

//构建一棵树 前序
TreeNode* creat_tree(char* str)
{
	_creat_tree(&str);
}

//前序遍历
void dlr_show(TreeNode* root)
{
	if(NULL == root) return;
	printf("%c ",root->data);
	dlr_show(root->left);
	dlr_show(root->right);
}

void ldr_show(TreeNode* root)
{
	if(NULL == root) return;
	ldr_show(root->left);
	printf("%c ",root->data);
	ldr_show(root->right);
}

void lrd_show(TreeNode* root)
{
	if(NULL == root) return;
	lrd_show(root->left);
	lrd_show(root->right);
	printf("%c ",root->data);
}

int high_tree(TreeNode* root)
{
	if(NULL == root) return 0;
	int left_high=high_tree(root->left);
	int right_high=high_tree(root->right);
	return left_high>right_high?left_high+1:right_high+1;
}

int desity_tree(TreeNode* root)
{
	if(NULL == root) return 0;
	return desity_tree(root->left)+desity_tree(root->right)+1;
}

TreeNode* left_tree(TreeNode* root,TREE_TYPE data)
{
	if(NULL == root) return NULL;
	if(root->data == data)
		return root->left;
	TreeNode* left=left_tree(root->left,data);
	TreeNode* right=left_tree(root->right,data);
	return left?left:right;

}

//插入
bool insert_tree(TreeNode* root,TREE_TYPE pdata,TREE_TYPE data)
{
	if( NULL==root) return false;
	if(root->data ==pdata)
	{
		if(NULL==root->left)
			return root->left=creat_tree_node(data);
		if(NULL==root->right)
			return root->right=creat_tree_node(data);
		return false;
	}
	bool lflag=insert_tree(root->left,pdata,data);
	bool rflag=insert_tree(root->right,pdata,data);
	return lflag || rflag;
}

bool del_tree(TreeNode** root,TREE_TYPE data)
{
	if(NULL == *root) return false;
	if((*root)->data == data)
	{
		if((*root)->left || (*root)->right) return false;
		free(*root);
		*root=NULL;
		return true;
	}
	if(del_tree(&(*root)->left,data)) return true;
	return del_tree(&(*root)->right,data);
}

void destroy_tree(TreeNode* root)
{
	if(NULL == root) return;
	destroy_tree(root->left);
	destroy_tree(root->right);
	free(root);
}
int main(int argc,const char* argv[])
{
	TreeNode* root=creat_tree("ABDG##H###CEI###F#J##");
	dlr_show(root);
	printf("\n");
	ldr_show(root);
	printf("\n");
	lrd_show(root);
	printf("\n%c\n",left_tree(root,'A')->data);
	destroy_tree(root);
	root=NULL;
}

有序二叉树:(二叉排序树、二叉搜索树、二叉查找树)

    左子树的数据小于根节点,根节点的数据小于等于右子树,并且左右子树都符合以上定义

    注意:由于这种树的中序遍历是从小到大,所以有序二叉树也是一种排序算法,并且有序二叉树中查找某个值,天然是二分查找

    注意:由于有序二叉树需要频繁地插入删除,因此不适合使用顺序存储

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

//有序二叉树

typedef struct TreeNode
{
	int data;
	struct TreeNode* left;
	struct TreeNode* right;
}TreeNode;

TreeNode* creat_tree_node(int data)
{
	TreeNode* node=malloc(sizeof(TreeNode));
	node->data=data;
	node->left=NULL;
	node->right=NULL;
	return node;
}

void _insert_tree(TreeNode** root,TreeNode* node)
{
	if(NULL==*root)
	{
		*root=node;
		return;
	}
	if(node->data <(*root)->data)
	{
		_insert_tree(&(*root)->left,node);
	}
	else
	{
		_insert_tree(&(*root)->right,node);
	}
}

//添加节点
void insert_tree(TreeNode** root,int data)
{
	_insert_tree(root,creat_tree_node(data));
}
//前序遍历
void dlr_show(TreeNode* root)
{
	if(NULL == root) return;
	printf("%d ",root->data);
	dlr_show(root->left);
	dlr_show(root->right);
}

void ldr_show(TreeNode* root)
{
	if(NULL == root) return;
	ldr_show(root->left);
	printf("%d ",root->data);
	ldr_show(root->right);
}

void lrd_show(TreeNode* root)
{
	if(NULL == root) return;
	lrd_show(root->left);
	lrd_show(root->right);
	printf("%d ",root->data);
}

//查找
bool query_tree(TreeNode* root,int data)
{
	if(NULL==root) return false;
	if(root->data == data) return true;
	if(root->data >data) 
		return query_tree(root->left,data);
	return query_tree(root->right,data);
}

//高度
int high_tree(TreeNode* root)
{
	if(NULL == root) return 0;
	int left_high=high_tree(root->left);
	int right_high=high_tree(root->right);
	return left_high>right_high?left_high+1:right_high+1;
}


//密度
int desity_tree(TreeNode* root)
{
	if(NULL == root) return 0;
	return desity_tree(root->left)+desity_tree(root->right)+1;
}

//销毁
void destroy_tree(TreeNode* root)
{
	if(NULL == root) return;
	destroy_tree(root->left);
	destroy_tree(root->right);
	free(root);
}

bool _access_ldr_tree(TreeNode* root,size_t index,int* val,int* k)
{
	if(NULL==root) return false;
	if(_access_ldr_tree(root->left,index,val,k)) return true;
	if((*k)++ == index)
	{
		*val=root->data;
		return true;
	}
	return _access_ldr_tree(root->right,index,val,k);
}

//按中序访问
bool access_ldr_tree(TreeNode* root,size_t index,int* val)
{
	int k=0;
	//递归需要使用同一个k来计数,所以需要共享一个变量k
	return _access_ldr_tree(root,index,val,&k);
}

//按值删除
bool del_val_tree(TreeNode** root,int data)
{
	if(NULL == *root) return false;
	if(data==(*root)->data)
	{
		TreeNode* temp=*root;
		*root=temp->left;
		_insert_tree(root,temp->right);
		free(temp);
		return true;
	}
	if(data < (*root)->data)
		return del_val_tree(&(*root)->left,data);
	return del_val_tree(&(*root)->right,data);
}

//判断是否平衡
bool is_AVL_tree(TreeNode* root)
{
	if(NULL==root) return true;
	int lh=high_tree(root->left);
	int rh=high_tree(root->right);
	return abs(lh - rh)<=1 && is_AVL_tree(root->left) && is_AVL_tree(root->right);
}

int main(int argc,const char* argv[])
{
	TreeNode* root =NULL;
	for(int i=0;i<10;i++)
	{
		int data=rand()%100;
		printf("%d ",data);
		insert_tree(&root,data);
	}
	del_val_tree(&root,83);
	del_val_tree(&root,77);
	printf("\n");
	dlr_show(root);
	printf("\n");
	ldr_show(root);
	printf("\nquery:%d\n",query_tree(root,83));
	int val=-1;
	access_ldr_tree(root,0,&val);
	printf("val:%d\n",val);
}

线索二叉树:

    也是有序二叉树

    规律:在一颗有n个节点的链式二叉树必定存在n+1个空指针

    因此链式二叉树中有很多空指针,可以在有序二叉树中,让这些空指针指向下一个或者前一个节点,这样有序遍历树时,可以不使用递归,而是使用循环进行,以此提高树的遍历效率

    中序线索二叉树

        节点数据项:

            数据

            左子树指针

            右子树指针

            右子树线索标志位(假:右子树指针指向真的右子树 真:右子树指针指向下一个节点)

    实现过程:

        1、创建一颗有序二叉树

        2、通过中序遍历创建线索(只需一次)

        3、根据线索遍历(循环)

    简答题:线索二叉树就是为了提高树的遍历熟读、效率,相当于链式变成了顺序

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

//线索二叉树

typedef struct TreeNode
{
	int data;
	struct TreeNode* left;
	struct TreeNode* right;
	bool rclue;
}TreeNode;

TreeNode* creat_tree_node(int data)
{
	TreeNode* node=malloc(sizeof(TreeNode));
	node->data=data;
	node->left=NULL;
	node->right=NULL;
	node->rclue=false;
	return node;
}

void _insert_tree(TreeNode** root,TreeNode* node)
{
	if(NULL == *root)
	{
		*root = node;
		return;
	}
	if(node->data < (*root)->data)
		_insert_tree(&(*root)->left,node);
	else
		_insert_tree(&(*root)->right,node);
}

void insert_tree(TreeNode** root,int data)
{
	_insert_tree(root,creat_tree_node(data));
}

void ldr_show(TreeNode* root)
{
	if(NULL == root) return;
	ldr_show(root->left);
	printf("%d ",root->data);
	ldr_show(root->right);
}

//prev是root的上一个节点
TreeNode* prev=NULL;

//根据中序,建立线索
void creat_clue(TreeNode* root)
{
	if(NULL == root) return;
	creat_clue(root->left);
	if(NULL != prev && NULL == prev->right)
	{
		prev->right = root;
		prev->rclue = true;
	}
	prev=root;
	creat_clue(root->right);
}

//按照线索遍历
void clue_show(TreeNode* node)
{
	while(node)
	{
		while(node->left) node=node->left;
		
		printf("%d ",node->data);
		while(node->rclue)
		{
			node = node->right;
			printf("%d ",node->data);
		}
		node=node->right;
	}
}

int main(int argc,const char* argv[])
{
	TreeNode* root =NULL;
	for(int i=0;i<10;i++)
	{
		int data=rand()%100;
		insert_tree(&root,data);
	}
	ldr_show(root);
	creat_clue(root);
	printf("\n");
	clue_show(root);
}

选择树:

    是一种完全二叉树,把要存储的数据存放在最后一层,根节点是左右子树的其中一个,可以是最大的或者最小的

    选择树的功能是快速地找出其中最大(胜者树)或最小值(败者树)

堆:

    是一颗完全二叉树,不适合链式存储的树

    大顶堆(大根堆):

        根节点比左右子树大

    小顶堆(小跟堆):

        根节点比左右子树小

    数据项:

        存储数据内存的首地址

        容量

        数量

    运算:

        创建、销毁、添加、删除、空堆、满堆、堆顶

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

#define TYPE int

#define SWAP(a,b) {typeof(a) t = (a);(a)=(b);(b)=t;}
//大顶堆

typedef struct Heap
{
		TYPE* arr;
		size_t cal;
		size_t cnt;
}Heap;


//创建
Heap* creat_heap(int cal)
{
	Heap* heap = malloc(sizeof(Heap));
	heap->arr= malloc(sizeof(TYPE)*cal);
	heap->cal=cal;
	heap->cnt =0;
	return heap;
}

//空堆
bool empty_heap(Heap* heap)
{
	return 0==heap->cnt;
}

//满堆
bool full_heap(Heap* heap)
{
	return heap->cnt >= heap->cal;
}

//添加
bool add_heap(Heap* heap,TYPE data)
{
	if(full_heap(heap)) return false;
	heap->arr[heap->cnt++]=data;
	//新加入的位置进行调整成大顶堆	
	int index=heap->cnt; //编号
	while(index>1)
	{
		if(heap->arr[index/2-1]<heap->arr[index-1])
		{
			SWAP(heap->arr[index/2-1],heap->arr[index-1]);
			index/=2;
			continue;
		}
		return true;

	}
	return true;
}

void show_heap(Heap* heap)
{
	for(int i=0;i<heap->cnt;i++)
	{
		printf("%d ",heap->arr[i]);
	}
	printf("\n");
}
int main(int argc,const char* argv[])
{
	Heap* heap=creat_heap(10);
	for(int i=0;i<10;i++)
	{
		add_heap(heap,rand()%100);
	}
	show_heap(heap);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值