• 二叉树


    1.二叉树

    1. 定义:

    是每个节点最多只能有两个儿子的树。

    2.应用

    查找树:所有节点左小右大

    平衡树:左右子树深度差1

    判定数:分支查找树(例如12个球如何只称3次就能分出轻重)

    带权树:路径带权

    最优树:带权路径长度最短的树,通信中的压缩编码

    2.查找二叉树

    1.定义

    为每个节点指定一个关键值,每个节点的左子树的关键值都小于节点的关键值,而右子树的关键值都大于节点的关键值。

    或者是一颗空树,或者是具有如下性质的非空二叉树:

    (1)若左子树不为空,左子树的所有结点的值均小于根的值;

    (2)若右子树不为空,右子树的所有结点均大于根的值;

    (3)它的左右子树也分别为二叉排序树。

    平均深度为O(logN)。

    2. 查找二叉树的实现

    1.fatal.h

    #include <stdio.h>
    #include<stdlib.h>
    
    #define Error(str) FatalError(str)
    #define FatalError(str) fprintf(stderr,"%s
    ",str),system("pause"),exit(1)
    

      

    2.searchtree.h

    #include<stdio.h>
    typedef int ElementType;
    
    #ifndef _Tree_H
    
    struct TreeNode;
    typedef struct TreeNode *Position;
    typedef struct TreeNode *SearchTree;
    
    SearchTree MakeEmpty(SearchTree T);
    Position Find(ElementType X, SearchTree T);
    Position FindMin(SearchTree T);
    Position FindMax(SearchTree T);
    SearchTree Insert(ElementType X, SearchTree T);
    SearchTree Delete(ElementType X, SearchTree T);
    ElementType Retrieve(Position P);
    void Preorder(SearchTree T);
    
    #endif
    

      

    3.searchtree.c

    #include "searchtree.h"
    #include "fatal.h"
    #include <stdio.h>
    #include <stdlib.h>
    
    struct TreeNode
    {
    	ElementType Element;
    	SearchTree Left;
    	SearchTree Right;
    };
    
    
    SearchTree MakeEmpty(SearchTree T)
    {
    	if (T!=NULL)
    	{
    		MakeEmpty(T->Left);
    		MakeEmpty(T->Right);
    		free(T);
    	}
    	return NULL;
    }
    
    /*

      在二叉排序树b中查找x的过程为:

    1. 若b是空树,则搜索失败,否则:
    2. 若x小于b的根节点的数据域之值,则搜索左子树;否则:
    3. 若x大于b的根节点的数据域之值,则搜索右子树;否则:
    4. x等于b的根节点数据域的值,查找成功。
    */
    Position Find(ElementType X, SearchTree T)
    {
    	if (T==NULL)
    	{
    		return NULL;
    	}
    	if (X < T->Element)
    	{
    		return Find(X, T->Left);
    	}
    	else if (X > T->Element)
    	{
    		return Find(X, T->Right);
    	}
    	else
    	{
    		return T;
    	}
    }
    
    Position FindMin(SearchTree T)
    {
    	if (T == NULL)
    	{
    		return NULL;
    	}
    	else if (T->Left == NULL)
    	{
    		return T;
    	}
    	else
    	{
    		return FindMin(T->Left);
    	}
    }
    
    Position FindMax(SearchTree T)
    {
    	//if (T == NULL)
    	//{
    	//	return NULL;
    	//}
    	//else if (T->Right == NULL)
    	//{
    	//	return T;
    	//}
    	//else
    	//{
    	//	return FindMax(T->Right);
    	//}
    	if (T != NULL)
    	{
    		while (T->Right != NULL)
    		{
    			T = T->Right;
    		}
    	}
    	return T;
    }
    
    ElementType Retrieve(Position P)
    {
    	return P->Element;
    }
    
    /*

      向一个二叉排序树b中插入一个结点s,过程为:

    1. 若b是空树,则将s所指结点作为根结点插入,否则:
    2. 若s->data小于b的根结点的数据域之值,则把s所指的节点插入到左子树,否则:
    3. 若s->data大于b的根结点的数据域之值,则把s所指结点插入到右子树中,否则:
    4. 把s->data等于根节点的数据域的值,已经存在,什么也不做。
    */
    SearchTree Insert(ElementType X, SearchTree T)
    {
    	if (T == NULL)
    	{
    		T = malloc(sizeof(struct TreeNode));
    		if (T == NULL)
    		{
    			FatalError("out of space!!!");
    		}
    		else
    		{
    			T->Element = X;
    			T->Left = T->Right = NULL;
    		}
    	}
    	else if (X < T->Element)
    		T->Left = Insert(X, T->Left);
    	else if (X > T->Element)
    		T->Right = Insert(X, T->Right);
    	return T;
    }
    
    /*
    1. 若x小于根节点的数据域的值,则删除左子树中X的值,否则
    2. 若x大于根节点的数据域的值,则删除右子树的x的值,否则
    3. 若根具有左子树和右子树,则删去根节点,从右子树的最小值作为新的根节点,并删去右子树的最小值,或者从左子树的最大值最为新的根节点,并删去左子树的最大值,否则
    4. 若根只有一个子树,则删去根节点,将子树返回,否则
    5. 该节点为叶子节点,直接删除
    */ SearchTree Delete(ElementType X, SearchTree T) { Position TmpCell; if (T == NULL) { Error("Element not found"); } else if (X < T->Element) T->Left = Delete(X, T->Left); else if (X>T->Right) T->Right = Delete(X, T->Right); else { if (T->Left && T->Right) { TmpCell = FindMin(T->Right); T->Element = TmpCell->Element; T->Right = Delete(T->Element, T->Right); } else { TmpCell = T; if (T->Left == NULL) { T = T->Right; } else if (T->Right == NULL) { T = T->Left; } free(TmpCell); } } return T; } void Preorder(SearchTree T) { if (T == NULL) { Error("Tree not found"); } if (T->Left != NULL) { Preorder(T->Left); } if (T->Right != NULL) { Preorder(T->Right); } printf("%d ", Retrieve(T)); }

      

    4.testsearchtree.c

    #include "fatal.h"
    #include "searchtree.h"
    #include <stdio.h>
    #include <stdlib.h>
    
    
    void main1()
    {
    	SearchTree T = NULL;
    	T = MakeEmpty(T);
    	int i = 0;
    	for (i = 0; i < 10;i++)
    	{
    		T= Insert(i, T);
    	}
    	Preorder(T);
    
    	for (i = 0; i < 10; i++)
    	{
    		T = Delete(i, T);
    	}
    
    	system("pause");
    }
    
    
    main()
    {
    	SearchTree T;
    	Position P;
    	int i;
    	int j = 0;
    
    	T = MakeEmpty(NULL);
    	for (i = 0; i < 50; i++)
    		T = Insert(i, T);
    	//for (i = 0; i < 50; i++, j = (j + 7) % 50)
    	//	T = Insert(j, T);
    
    	Preorder(T);
    
    	for (i = 0; i < 50; i++)
    		if ((P = Find(i, T)) == NULL /*|| Retrieve(P) != i*/)
    			printf("Error at %d
    ", i);
    
    	for (i = 0; i < 50; i ++)
    		T = Delete(i, T);
    
    	//for (i = 1; i < 50; i += 2)
    	//	if ((P = Find(i, T)) == NULL || Retrieve(P) != i)
    	//		printf("Error at %d
    ", i);
    	//for (i = 0; i < 50; i += 2)
    	//	if ((P = Find(i, T)) != NULL)
    	//		/*printf("Error at %d
    ", i);*/
    
    	printf("Min is %d, Max is %d
    ", Retrieve(FindMin(T)),
    		Retrieve(FindMax(T)));
    
    	system("pause");
    	return 0;
    }
    

    3. 平衡二叉树

    1.定义

    一棵AVL树是其每个节点的左子树和右左子树的高度最多差1的二叉查找树。

    节点的平衡因子BF=左子树深度-右子树深度。

    树的深度保持为O(logN)。

    2.平衡二叉树的实现

    1. avl.h

    #include <stdio.h>
    typedef int ElementType;
    
    #ifndef _AvlTree_H
    struct AvlNode;
    typedef struct AvlNode *Position;
    typedef struct AvlNode *AvlTree;
    
    AvlTree MakeEmpty(AvlTree T);
    Position Find(ElementType X, AvlTree T);
    Position FindMin(AvlTree T);
    Position FindMax(AvlTree T);
    AvlTree Insert(ElementType X, AvlTree T);
    AvlTree Delete(ElementType X, AvlTree T);
    ElementType Retrieve(Position P);
    
    #endif
    

      

    2.avl.c

    #include "avl.h"
    #include "fatal.h"
    #include <stdio.h>
    
    struct AvlNode
    {
    	ElementType Element;
    	AvlTree Left;
    	AvlTree Right;
    	int Height;
    };
    
    AvlTree MakeEmpty(AvlTree T)
    {
    	if (T != NULL)
    	{
    		MakeEmpty(T->Left);
    		MakeEmpty(T->Right);
    		free(T);
    	}
    	return NULL;
    }
    
    Position Find(ElementType X, AvlTree T)
    {
    	if (T == NULL)
    	{
    		return NULL;
    	}
    	if (X < T->Element)
    	{
    		return Find(X, T->Left);
    	}
    	if (X>T->Element)
    	{
    		return Find(X, T->Right);
    	}
    	return T;
    }
    
    Position FindMin(AvlTree T)
    {
    	if (T == NULL)
    	{
    		return NULL;
    	}
    	if (T->Left == NULL)
    	{
    		return T;
    	}
    	return FindMin(T->Left);
    }
    
    Position FindMax(AvlTree T)
    {
    	if (T!= NULL)
    	{
    		while (T->Right != NULL)
    		{
    			T = T->Right;
    		}
    	}
    	return T;
    }
    static int Height(Position P)
    {
    	if (P == NULL)
    	{
    		return -1;
    	}
    	else
    	{
    		return P->Height;
    	}
    }
    
    static Position SingleRoateWithLeft(Position K2)
    {
    	Position K1;
    	K1 = K2->Left;
    	K2->Left = K1->Right;
    	K2->Height = max(Height(K2->Left), Height(K2->Right)) + 1;
    	K1->Height = max(Height(K1->Left), K2->Height) + 1;
    	return K1;
    }
    static Position SingleRoateWithRight(Position K1)
    {
    	Position K2;
    	K2 = K1->Right;
    	K1->Right = K2->Left;
    	K2->Left = K1;
    
    	K1->Height = max(Height(K1->Left), Height(K1->Right)) + 1;
    	K2->Height = max(K1->Height, Height(K2->Right)) + 1;
    
    	return K2;
    }
    
    static Position DoubleRoateWithLeft(Position K3)
    {
    	K3->Left = SingleRoateWithRight(K3->Left);
    	return SingleRoateWithLeft(K3);
    }
    
    static Position DoubleRoateWithRight(Position K1)
    {
    	K1->Right = SingleRoateWithLeft(K1->Right);
    	return SingleRoateWithRight(K1);
    }
    
    AvlTree Insert(ElementType X, AvlTree T)
    {
    	//空树
    	if (T== NULL)
    	{
    		T = malloc(sizeof(struct AvlNode));
    		if (T == NULL)
    		{
    			FatalError("out of space!!!");
    		}
    		else
    		{
    			T->Element = X;
    			T->Height = 0;
    			T->Left = T->Right = NULL;
    		}
    	}
    	//X小于根节点的数据
    	else if (X < T->Element)
    	{
    		T->Left = Insert(X, T->Left);
    		if (Height(T->Left) - Height(T->Right) == 2)
    		{
    			if (X < T->Left->Element)
    			{
    				T = SingleRoateWithLeft(T);
    			}
    			else
    				T = DoubleRoateWithLeft(T);
    		}
    	}
    	//X大于根节点数据
    	else if (X > T->Element)
    	{
    		T->Right = Insert(X, T->Right);
    		if (Height(T->Right)- Height(T->Left) == 2)
    		{
    			if (X > T->Right->Element)
    			{
    				T = SingleRoateWithRight(T);
    			}
    			else
    			{
    				T = DoubleRoateWithRight(T);
    			}
    		}
    
    	}
    	//X等于根节点的数据,什么也不用做
    
    	T->Height = max(Height(T->Left), Height(T->Right)) + 1;
    	return T;
    }
    
    ElementType Retrieve(Position P)
    {
    	return P->Element;
    }
    
    AvlTree Delete(ElementType X, AvlTree T)
    {
    
    }
    
    void Inorder(AvlTree T)
    {
    	if (T == NULL)
    	{
    		Error("Empty Tree
    ");
    	}
    	if (T ->Left != NULL)
    	{
    		Inorder(T->Left);
    	}
    	printf("%d	", T->Element);
    	if (T->Right)
    	{
    		Inorder(T->Right);
    	}
    
    	printf("
    ");
    }
    

      

    3.testavl.c

    #include "avl.h"
    #include "fatal.h"
    #include <stdio.h>
    #include <stdlib.h>
    
    void main()
    {
    	AvlTree T = NULL;
    	T = MakeEmpty(T);
    
    	for (int i = 0; i < 10; i++)
    	{
    		T = Insert(i, T);
    	}
    
    	Inorder(T);
    
    	printf("Max = %d
    ", Retrieve(FindMax(T)));
    	printf("Min = %d
    ", Retrieve(FindMin(T)));
    
    	for (int i = 0; i < 10; i++)
    	{
    		if (Find(i,T) == NULL)
    		{
    			FatalError("Find error
    ");
    		}
    	}
    
    	system("pause");
    }
    

      

    4. 参考资源

    http://blog.csdn.net/hguisu/article/details/7686515

    http://blog.csdn.net/zealot_2002/article/details/8244436

  • 相关阅读:
    解决VM 安装Ubuntu64与 Device/Credential Guard 不兼容,显示不支持64位系统
    WPF处理内容溢出
    .NET Standard 2.0 是什麼?可以吃嗎?
    C#.Net]启动外部程序的几种常用方法汇总
    在C#中接收系统屏幕锁定和解锁的事件
    C#.Net]启动外部程序的几种常用方法汇总
    MongoDB索引的使用
    读取xml并将节点保存到Excal
    开学后的第一篇
    续并查集学习笔记——Gang团伙题解
  • 原文地址:https://www.cnblogs.com/my-cat/p/5971947.html
Copyright © 2020-2023  润新知