二叉树的实现

二叉树

本文有模仿部分,侵删


一棵二叉树T是一个有穷的结点集合。这个集合可以为空,若不为空,则它是由根结点和称为其左子树TL和右子树TR的两个不相交的二叉树组成。可见左子树和右子树还是二叉树。

特殊二叉树

二叉树的深度小于结点数N,可以证明平均深度是O(根号n)

“斜二叉树(Skewed Binary Tree)”(也称为退化二叉树);

“完美二叉树(Perfect Binary Tree)”。(也称为满二叉树)。

一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1 ≤ i ≤ n)的结点与满二叉树中编号为 i 的结点在二叉树中的位置相同,则这棵二叉树称为“完全二叉树(Complete Binary Tree)”。完全二叉树适合用数组存储

如图不是完全二叉树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qIFO2G5n-1644995320070)(C:\Users\Π\AppData\Roaming\Typora\typora-user-images\image-20211020202002263.png)]

二叉树的性质

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uHSEix7d-1644995320072)(C:\Users\Π\AppData\Roaming\Typora\typora-user-images\image-20211205125834500.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OkoW8GYS-1644995320073)(C:\Users\Π\AppData\Roaming\Typora\typora-user-images\image-20211205125854557.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E6iHnIIG-1644995320073)(C:\Users\Π\AppData\Roaming\Typora\typora-user-images\image-20211205125913247.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sU52IZGI-1644995320074)(C:\Users\Π\AppData\Roaming\Typora\typora-user-images\image-20211205125932870.png)]

二叉树的链表存储

LeftDataRight
指针数据指针
struct  TreeNode{
	ElementType  Data;
	struct  TreeNode*  Left;
	struct  TreeNode*  Right;
}typedef  struct  TreeNode *BinTree;
typedef  struct  TreeNode position;

二叉树的操作

类型名称:二叉树(BinTree)
数据对象集:一个有限的结点集合。这个集合可以为空,若不为空,则它是由根结点和其左、右二叉子树组成。
操作集:对于所有 BT, BT1, BT2  BinTree, Item  ElementType,重要的操作有:
1、Boolean IsEmpty( BinTree BT ): 若BT为空返回TRUE; 否则返回FALSE;
2、void Traversal( BinTree BT ):二叉树的遍历,即按某一顺序访问二叉树中的每个结点仅一次;
3、BinTree CreatBinTree( ):创建一个二叉树。

二叉树的创建

先序创建和层序创建

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HNmmjHZE-1644995320074)(C:\Users\Π\AppData\Roaming\Typora\typora-user-images\image-20211130195239804.png)]

二叉树的左右链存储结构(二叉链表)的建立

//方法1
BinTree CreateBT(datatype v, BinTree ltree , BinTree rtree )
{  
     BinTree  root ;
     root = new node ;
     root →data = v ;   
     root →lchild = ltree ; 
     root →rchild = rtree ;
     return  root ;  
}

//法二:我在这里实现的是,二叉树的前序遍历方式创建,如果要使用中序或者后序的方式建立二叉树,只需将生成结点和构造左右子树的顺序改变即可
 void CreateBiTree(BiTree T)
  {
      char ch;
      scanf("%c",&ch);
      if(ch=='#')
          T=NULL;
      else
     {
         T=(BiTree)malloc(sizeof(BiTNode));
         if(!T)
             exit(-1);
          T->data=ch;
          CreateBiTree(T->lchild);
         CreateBiTree(T->rchild);
      }
 }//注意:此法实际行不通
  //下面给出两解决法
//1
Binarytree recursion_creat(Binarytree T)
{
	char ch;
	scanf("%c", &ch);
	fflush(stdin);//清除标准输入流的缓存
	if (ch != '#')
	{
		T = (Binarytree)malloc(sizeof(TREE));
		T->data = ch;
		T->lson = NULL;
		T->rson = NULL;
		T->lson = recursion_creat(T->lson);
		T->rson = recursion_creat(T->rson);
	}
	return T;
}//完整代码见最底部


//下面是老师帮改的代码,有些地方还不对,记得还得再调
//树的操作
#include <iostream>
#define max 20
using namespace std;

//树的表示
struct Treenode{
	int data;
	struct Treenode *lchild;
	struct Treenode *rchild;
	struct Treenode *father;
};

//栈
typedef struct node{
	Treenode *s[max];
	int top;
}Stack;

void initStack(Stack *H);
void myPush(Stack *H, Treenode *T);
Treenode* myPop(Stack *H);
void inorder_create(Treenode*BT);//前序递归建树
void inorder_travel(Treenode*BT);//前序遍历
void midorder_travel(Treenode*BT);//中序遍历,非递归
void postorder_travel(Treenode*BT);//后序遍历
void level_order(Treenode*BT);//层序遍历



int main(){
	Treenode*T = new Treenode;
	inorder_create(T);
	inorder_travel(T);
	cout << '\n';
	midorder_travel(T);
	cout << '\n';
	postorder_travel(T);

	system("pause");
	return 0;
}

int arr[10] = { 1, 3, 4, 5, 61, 33, 15, 23, 34, 42 };
int x = 10;
//先序遍历建表
void inorder_create(Treenode *T){ 
	int m;
	cin >> m;
	if (m == -1){ 
		if (T->father == nullptr)
		{
			return;
		}
		else{
		if (T->father->lchild == T)
		{
			T->father->lchild = nullptr;
			delete T;
			T = nullptr;
		}
		else{
			T->father->rchild = nullptr;
			delete T;
			T = nullptr;
		}
		}
	}
	else{
		T->data = m;
		T->lchild = new Treenode;
		T->lchild->father = T;
		T->rchild = new Treenode;
		T->rchild->father = T;
		inorder_create(T->lchild);
		inorder_create(T->rchild);
	}
}

//先序遍历
void inorder_travel(Treenode *BT){
	if (BT == nullptr)
		return;
	cout << BT->data << '\t';
	inorder_travel(BT->lchild);
	inorder_travel(BT->rchild);
}

void midorder_travel(Treenode *BT){
	Treenode*T = BT;
	Stack *H = new Stack;
	initStack(H);
	while (T){
		myPush(H, T);
		T = T->lchild;
	}
	if (H->top != -1){
		T = myPop(H);
		cout << T->data << '\t';
		T = T->rchild;
	}
}

void postorder_travel(Treenode *BT){
	if (!BT)
		return;
	postorder_travel(BT->lchild);
	postorder_travel(BT->rchild);
	cout << BT->data << '\t';
}

void initStack(Stack *H){
	if (!H)
		return;
	for (int i = 0; i < max; i++){
		H->s[i] = new Treenode;
	}
	H->top = -1;
}

void myPush(Stack *H, Treenode *T){
	if (H->top == max - 1){
		cout << "栈满" << endl;
		return;
	}
	H->s[++H->top] = T;
}

Treenode* myPop(Stack *H){
	if (H->top == -1)
		return nullptr;
	return H->s[H->top--];
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZhsbukxN-1644995320074)(C:\Users\Π\AppData\Roaming\Typora\typora-user-images\image-20211205130413520.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wgpN3Emv-1644995320075)(C:\Users\Π\AppData\Roaming\Typora\typora-user-images\image-20211205130439346.png)]

遍历(递归)

//先序遍历
void PreOrderTraversal( BinTree BT )
{
    if( BT ) {
        printf(%d”, BT->Data)//放中间变成中序,放最后变成后序
        PreOrderTraversal( BT->Left );
        PreOrderTraversal( BT->Right );
    }
}//要能判断遍历的顺序,三种序列走的路径相同,只是不同节点在不同序列中被print出来有先后

//中序遍历
void InOrderTraversal( BinTree BT ) {
 if( BT ) {
 InOrderTraversal( BT->Left );
 printf(%d”, BT->Data);
 InOrderTraversal( BT->Right );
 } }

//后序遍历
void PostOrderTraversal( BinTree BT ) {
 if( BT ) {
 PostOrderTraversal( BT->Left );
 PostOrderTraversal( BT->Right);
 printf(%d”, BT->Data);
 } }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6cWdAD3p-1644995320075)(C:\Users\Π\AppData\Roaming\Typora\typora-user-images\image-20211020203518183.png)]

二叉树非递归遍历(使用堆栈)

中序遍历

 遇到一个结点,就把它压栈并访问它,然后去遍历它的左子树;
 当左子树遍历结束后,从栈顶弹出这个结点;
 然后按其右指针再去中序遍历该结点的右子树。

void InOrderTraversal( BinTree BT )
{   BinTree T=BT;
Stack S = CreatStack( MaxSize ); /*创建并初始化堆栈S*/
while( T || !IsEmpty(S) ){
    while(T){   /*一直向左并将沿途结点压入堆栈*/
        Push(S,T); 
        T = T->Left; 
    }
    if(!IsEmpty(S)){
        T = Pop(S); /*结点弹出堆栈*/
        printf(%5d”, T->Data); /*(访问)打印结点,放到前面合适位置变成先序*/
        T = T->Right; /*转向右子树*/
    }
}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FCHzuF4T-1644995320076)(C:\Users\Π\AppData\Roaming\Typora\typora-user-images\image-20211129233657165.png)]

后序遍历的非递归算法


int* postorderTraversal(BinTree root, int* returnSize)
{
    if( root == NULL ) return NULL;
    /**自定义结果数组并初始化**/
    int* result = (int*)malloc(1000*sizeof(int));
    int len = 0;
    /**定义栈并初始化**/
    Sq_stack* stk_result = (Sq_stack*)malloc(sizeof(Sq_stack));
    initStack(stk_result);
    Sq_stack* temp_stk = (Sq_stack*)malloc(sizeof(Sq_stack));
    initStack(temp_stk);
 
    while( root || !isEmptyStack(temp_stk) )
    {
        /**将当前结点同时入临时栈和结果栈【根】,并遍历右子树----【右】**/
        while( root )
        {
            Push(temp_stk,root);
            Push(stk_result,root);
            root = root->right;
        }
        /**当右子树遍历结束后,弹出临时栈栈顶结点,并遍历其左子树----【左】,继续while**/
        if( !isEmptyStack(temp_stk) )
        {
            root = Pop(temp_stk);
            root = root->left;
        }
    }
    /**当所有结点都访问完,即最后访问的树节点为空且临时栈也为空时,
        主算法结束,依次pop出结果栈结点**/
    BinTree e = (BinTree)malloc(sizeof(Position));
    while( !isEmptyStack(stk_result) )
    {
        e = Pop(stk_result);
        result[len++] = e->data;
    }
    free(e);
    *returnSize = len;
    return result;
}

层序遍历(队列实现)

void LevelOrderTraversal ( BinTree BT )
{   Queue Q;  BinTree T;
if ( !BT ) return; /* 若是空树则直接返回 */
Q = CreatQueue( MaxSize ); /*创建并初始化队列Q*/
AddQ( Q, BT );//根节点入队
while ( !IsEmptyQ( Q ) ) {
    T = DeleteQ( Q );//从开头抛出一个元素
printf(%d\n”, T->Data); /*访问取出队列的结点*/
if ( T->Left )  AddQ( Q, T->Left );
if ( T->Right )  AddQ( Q, T->Right );
}
}
//最终实现了一层一层访问

遍历二叉树的应用

例一:输出二叉树中的叶子结点

void PreOrderPrintLeaves( BinTree BT )
{
    if( BT ) {//左右节点都为空
        if ( !BT-Left && !BT->Right )
            printf(%d ”, BT->Data );
        PreOrderPrintLeaves ( BT->Left );
        PreOrderPrintLeaves ( BT->Right );
    }
}

例二:求二叉树的高度

//求左右子树的最大高度
int PostOrderGetHeight( BinTree BT )
{   int HL, HR, MaxH;
    if( BT ) {
        HL = PostOrderGetHeight(BT->Left);  /*求左子树的深度*/
        HR = PostOrderGetHeight(BT->Right); /*求右子树的深度*/
        MaxH = HL > HR? HL : HR; /*取左右子树较大的深度*/
        return ( MaxH + 1 ); /*返回树的深度*/
    }
    else  return 0; /* 空树深度为0 */
}

例三:二元运算表达式树及其遍历

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F9cTdoMG-1644995320077)(C:\Users\Π\AppData\Roaming\Typora\typora-user-images\image-20211130194734973.png)]

例四:由两种遍历来确定一棵树(要唯一确定必须的有中序遍历结果)

没有中序的困扰:
 先序遍历序列:A B
 后序遍历序列:B A 确定不了B是A的左孩子还是右孩子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-chrQcQ5w-1644995320077)(C:\Users\Π\AppData\Roaming\Typora\typora-user-images\image-20211130195022624.png)]

代码

//树的操作,带父节点
#include <iostream>
#define max 20
using namespace std;

//树的表示
struct Treenode{
	int data;
	struct Treenode *lchild;
	struct Treenode *rchild;
	struct Treenode *father;
};

//栈
typedef struct node{
	Treenode *s[max];
	int top;
}Stack;

void initStack(Stack *H);
void myPush(Stack *H, Treenode *T);
Treenode* myPop(Stack *H);
void inorder_create(Treenode*BT);//前序递归建树
void inorder_travel(Treenode*BT);//前序遍历
void midorder_travel(Treenode*BT);//中序遍历,非递归
void postorder_travel(Treenode*BT);//后序遍历
void level_order(Treenode*BT);//层序遍历



int main(){
	Treenode*T = new Treenode;
	inorder_create(T);
	inorder_travel(T);
	cout << '\n';
	midorder_travel(T);
	cout << '\n';
	postorder_travel(T);

	system("pause");
	return 0;
}

int arr[10] = { 1, 3, 4, 5, 61, 33, 15, 23, 34, 42 };
int x = 10;
//先序遍历建表
void inorder_create(Treenode *T){
	int m;
	cin >> m;
	if (m == -1){
		if (T->father == nullptr)
		{
			return;
		}
		else{
			if (T->father->lchild == T)
			{
				T->father->lchild = nullptr;
				delete T;
				T = nullptr;
			}
			else{
				T->father->rchild = nullptr;
				delete T;
				T = nullptr;
			}
		}
	}
	else{
		T->data = m;
		T->lchild = new Treenode;
		T->lchild->father = T;
		T->rchild = new Treenode;
		T->rchild->father = T;
		inorder_create(T->lchild);
		inorder_create(T->rchild);
	}
}

//先序遍历
void inorder_travel(Treenode *BT){
	if (BT == nullptr)
		return;
	cout << BT->data << '\t';
	inorder_travel(BT->lchild);
	inorder_travel(BT->rchild);
}

void midorder_travel(Treenode *BT){
	Treenode*T = BT;
	Stack *H = new Stack;
	initStack(H);
	while (T){
		myPush(H, T);
		T = T->lchild;
	}
	if (H->top != -1){
		T = myPop(H);
		cout << T->data << '\t';
		T = T->rchild;
	}
}

void postorder_travel(Treenode *BT){
	if (!BT)
		return;
	postorder_travel(BT->lchild);
	postorder_travel(BT->rchild);
	cout << BT->data << '\t';
}

void initStack(Stack *H){
	if (!H)
		return;
	for (int i = 0; i < max; i++){
		H->s[i] = new Treenode;
	}
	H->top = -1;
}

void myPush(Stack *H, Treenode *T){
	if (H->top == max - 1){
		cout << "栈满" << endl;
		return;
	}
	H->s[++H->top] = T;
}

Treenode* myPop(Stack *H){
	if (H->top == -1)
		return nullptr;
	return H->s[H->top--];
}

完整c语言代码(转载)

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

typedef struct Binary_Tree
{
	char data;   //结点的数据域
	struct Binary_Tree *lson;
	struct Binary_Tree *rson;
}TREE, *Binarytree;
//各函数声名
Binarytree recursion_creat(Binarytree T); //运用递归方法创建二叉树
void preorder_traversal(Binarytree T);    //前序遍历
void inorder_traversal(Binarytree T);     //非递归实现中序遍历
void postorder_traversal(Binarytree T);   //非递归实现后序遍历
void exchange_subtree(Binarytree T);      //交换左右子树
int height_calculation(Binarytree T);     //统计高度
void swap(Binarytree Tree1, Binarytree Tree2);
int main()
{
	Binarytree T1, T2;
	int height, flag = 1;
	printf("请依次输入节点的值,以'#'号结束\n\n");
	T2 = recursion_creat(T1);
	printf("\n\n创建成功!\n\n");
	while (flag = 1)
	{
		printf("-----------------------------------");
		printf("\n");
		printf("--------1 输出前序遍历结果----------\n\n");
		printf("--------2 输出中序遍历结果----------\n\n");
		printf("--------3 输出后序遍历结果----------\n\n");
		printf("--------4 交换左右子树--------------\n\n");
		printf("--------5 统计二叉树的高度----------\n\n");
		printf("--------6 退出----------------------\n\n");
		printf("\n\n请输入您的选择:");
		int m;
		scanf("%d", &m);
		switch (m)
		{
		case 1:
			printf("\n\n前序遍历结果为:\n\n");
			preorder_traversal(T2);
			printf("\n\n");
			break;
		case 2:
			printf("\n\n中序遍历结果为:\n\n");
			inorder_traversal(T2);
			printf("\n\n");
			break;
		case 3:
			printf("\n\n后序遍历结果为:\n\n");
			postorder_traversal(T2);
			printf("\n\n");
			break;
		case 4:
			exchange_subtree(T2);
			printf("交换成功!");
			printf("\n\n");
			break;
		case 5:
			printf("\n\n此二叉树的高度为:\n\n");
			height = height_calculation(T2);
			printf("%d", height);
			printf("\n\n");
			break;
		case 6:exit(0);
		default:printf("输入错误!"); break;
		}
	}
	return 0;
}
Binarytree recursion_creat(Binarytree T)
{
	char ch;
	scanf("%c", &ch);
	fflush(stdin);//清除标准输入流的缓存
	if (ch != '#')
	{
		T = (Binarytree)malloc(sizeof(TREE));
		T->data = ch;
		T->lson = NULL;
		T->rson = NULL;
		T->lson = recursion_creat(T->lson);
		T->rson = recursion_creat(T->rson);
	}
	return T;
}

void preorder_traversal(Binarytree T)
{
	if (T != NULL)
	{
		printf("%c", T->data);
		//依次遍历左子树和右子树
		preorder_traversal(T->lson);
		preorder_traversal(T->rson);
	}
}
void inorder_traversal(Binarytree T)
{
	int index = 0;    //栈顶
	Binarytree data[100];
	do
	{
		while (T != NULL)
		{
			index++;
			data[index] = T;
			T = T->lson;
		}
		if (index != 0)
		{
			T = data[index];
			index--;
			printf("%c", T->data);
			T = T->rson;
		}
	} while (T != NULL || index != 0);
}

void postorder_traversal(Binarytree T)
{
	Binarytree S[100], P;
	int flag, top = 0;
	if (T != NULL)
	{
		do{
			while (T != NULL)
			{
				S[top++] = T; //入栈
				T = T->lson;//遍历左子树
			}
			P = NULL;//
			flag = 1;    //已访问
			while (top && flag)
			{
				T = S[top - 1]; //退栈
				if (T->rson == P)  //
				{
					printf("%c", T->data);//访问
					top--;
					P = T;//
				}
				else
				{
					T = T->rson;
					flag = 0;
				}
			}
		} while (top);
		printf("\n\n");
	}
}

void exchange_subtree(Binarytree T)
{
	if (!T))
	{
		return;//退出

	}
	else
	{
		swap(T->lson, T->rson);
		exchange_subtree(T->lson);
		exchange_subtree(T->rson);
	}
}

void swap(Binarytree Tree1, Binarytree Tree2)
{
	Binarytree temp;
	temp = Tree1;
	Tree1 = Tree2;
	Tree2 = temp;
}

int height_calculation(Binarytree T)
{
	int height_lson;
	int height_rson;
	int max;
	if (T == NULL)
	{
		return 0;
	}
	height_lson = height_calculation(T->lson);
	height_rson = height_calculation(T->rson);
	max = height_lson > height_rson ? height_lson : height_rson;
	return max + 1;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值