数据结构——树

二叉树

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

typedef int myType;

typedef struct treeNode 
{
    myType element;     //值域元素
    struct treeNode *lchild;    //左孩子
    struct treeNode *rchild;    //右孩子
}Btree;

void createTree(Btree **T)  //传入一个Btree的指针的地址
{
    myType data;
    scanf("%d", &data);

    if(data == -1) {    //-1代表终端节点值
        *T = NULL;
    } else {
        *T = (Btree *)malloc(sizeof(struct treeNode));  
        (*T)->element = data;
        printf("请输入%d的左孩子节点:", data);
        createTree(&((*T)->lchild));
        printf("请输入%d的右孩子节点:", data);
        createTree(&((*T)->rchild));
    }
}

void preOrder(Btree *T)
{
    if(T != NULL) {
        printf("%d ", T->element);  //访问根节点
        preOrder(T->lchild);    //先根序遍历左子树
        preOrder(T->rchild);    //先根序遍历右子树
    }
}

void inOrder(Btree *T)
{
    if(T != NULL) {
        inOrder(T->lchild);     //中根序遍历左子树
        printf("%d ", T->element);  //访问根节点 
        inOrder(T->rchild); //中根序遍历右子树
    }
}

void postOrder(Btree *T)
{
    if(T != NULL) {
        postOrder(T->lchild);   //后根序遍历左子树
        postOrder(T->rchild);   //后根序遍历右子树
        printf("%d ", T->element);  //访问根节点
    }
}
/*层序遍历(bfs)
void levelOrder(Btree *T)
{
    QUEUE *q = createQueue(100);    //创建一个容量为100的队列

    while(T != NULL) {
        printf("%d ", T->element);  //访问根节点
        if(T->lchild != NULL)
            enQueue(T->lchild, q);  //如果左孩子存在,左孩子入队
        if(T->rchild != NULL)
            enQueue(T->rchild, q);  //如果右孩子存在,右孩子入队
        if(!isEmpty(q))     //当队列非空时
            T = frontAndDequeue(q); //队头元素出队,并且访问出队元素
        else
            T = NULL;   //队列为空,遍历完成
    }

    disposeQueue(q);    //销毁队列
}
*/
void distroyTree(Btree **T)
{
    Btree *pl, *pr;
    if((*T) == NULL) {
        return ;
    } else {
        pl = (*T)->lchild;  //保存左孩子的地址
        pr = (*T)->rchild;  //保存右孩子的地址
        (*T)->lchild = NULL;
        (*T)->rchild = NULL;
        free(*T);   //释放根节点
        (*T) = NULL;
        distroyTree(&pl);   //递归销毁
        distroyTree(&pr);
    }
}

int tree_deep(Btree *T)
{
    int deep = 0;
    if(T) {
        int leftdeep = tree_deep(T->lchild);    
        int rightdeep = tree_deep(T->rchild);
        deep = leftdeep > rightdeep ? leftdeep+1 : rightdeep+1;
    }

    return deep;
}

int leafnode_count(Btree *T, int num)
{
    if(T) {
        if(T->lchild == NULL && T->rchild == NULL) 
            num++;
        leafnode_count(T->lchild, num);
        leafnode_count(T->rchild, num);
    }   

    return num;
}

int main()
{
    system("pause");
    return 0;
}

二叉搜索树

#include<stdio.h>/*二叉查找树:左子树中所有关键字值小于结点关键字值X,右子树中所有关键字值大于X*/
#include<stdlib.h>
 
#ifndef _Tree_H

 struct TreeNode;
 typedef struct TreeNode *Position;
 typedef struct TreeNode *SreachTree;
 typedef int ElementType;

 SreachTree MakeEmpty(SreachTree T);
 Position Find(ElementType X,SreachTree T);
 Position FindMin(SreachTree T);
 Position FindMax(SreachTree T);
 SreachTree Insert(ElementType X,SreachTree T);
 SreachTree Delete(ElementType X,SreachTree T);
 ElementType Retrieve(Position P);

#endif

struct TreeNode
{
    ElementType Element;
    SreachTree Left;
    SreachTree Right;
};

 SreachTree MakeEmpty(SreachTree T)
 {
     if(T!=NULL)
     {
         MakeEmpty(T->Left);
         MakeEmpty(T->Right);
         free(T);
     }
     return NULL;
 }

 Position Find(ElementType X,SreachTree 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(SreachTree T)
 {
     if(T==NULL)return NULL;
     else if(T->Left==NULL)return T;
     else return FindMin(T->Left);
 }

 Position FindMax(SreachTree T)
{
    if(T!=NULL)
    {
        while(T->Right!=NULL)
        {
            T=T->Right;
        }
    }
    return T;
}

 SreachTree Insert(ElementType X,SreachTree T)
 {
     if(T==NULL)
     {
         T=(struct TreeNode*)malloc(sizeof(struct TreeNode));
         if(T==NULL)printf("Out of space!\n");
         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;
     
 }

 SreachTree Delete(ElementType X,SreachTree T)
{
    Position Tmpcell;
    if(T==NULL)printf("Element not found!\n");
    else if(X<T->Element)
    {
        T->Left=Delete(X,T->Left);
    }
    else if(X>T->Element)
    {
        T->Right=Delete(X,T->Right);
    }
    else if(T->Left&&T->Right)//X结点有两个孩子
    {
        Tmpcell=FindMin(T->Right);
        T->Element=Tmpcell->Element;
        T->Right=Delete(T->Element,T->Right);
    }
    else//X结点有一个或者没有子节点 
    {
        Tmpcell=T;
        if(T->Left==NULL)T=T->Right;
        else if(T->Right==NULL)T=T->Left;
        free(Tmpcell);
    }
    return T;
}

 ElementType Retrieve(Position P)
 {
     return P->Element;
 }

 int main()
 {
     system("pause");
     return 0;
 }

AVL树

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

#ifndef _AVLTree_H

struct AvlNode;
typedef struct AvlNode *Position;
typedef struct AvlNode *AvlTree;
typedef int ElementType;

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

struct AvlNode
{
    ElementType Element;
    AvlTree Left;
    AvlTree Right;
    int Height;
};

int Max(int a,int b)
{
    if(a>b)return a;
    else return b;
}

AvlTree MakeEmpty(AvlTree T)
{
    if(T!=NULL)
    {
        MakeEmpty(T->Left);
        MakeEmpty(T->Right);
        free(T);
        T->Height=0;
    }
}

Position Find(ElementType X,AvlTree 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(AvlTree T)
{
     if(T==NULL)return NULL;
     else if(T->Left==NULL)return T;
     else 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 SingleRotateWithLeft(Position K2)
{
    Position K1;
    K1=K2->Left;
    K2->Left=K1->Right;
    K1->Right=K2;

    K2->Height=Max(Height(K2->Left),Height(K2->Right))+1;
    K1->Height=Max(Height(K1->Left),K2->Height)+1;
    
    return K1;
}

static Position SingleRotateWithRight(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 DoubleRotateWithLeft(Position K3)
{
    K3->Left=SingleRotateWithRight(K3->Left);

    return SingleRotateWithLeft(K3);
}

static Position DoubleRotateWithRight(Position K3)
{
    K3->Right=SingleRotateWithLeft(K3->Right);
    
    return SingleRotateWithRight(K3);
}

AvlTree Insert(ElementType X,AvlTree T)
{
    if(T == NULL){
        /*
         * 一般情况为递归调用的最后一层,执行插入操作
         */
        T =(struct AvlNode*) malloc(sizeof(struct AvlNode));
        if(T == NULL){
            //内存不足异常
        }else{
            T -> Element = X;
            T -> Left = T -> Right = NULL;
            T -> Height = 0;
        }
    }else if(X < T -> Element){
        /*
         * 往左边递归插入
         */
        T -> Left = Insert(X,T -> Left);
        //插入完成判断当前节点下的左子树与右子树的高度差,确定不平衡点
        if(Height(T -> Left) - Height(T -> Right) == 2){
            //中间节点(T的左边节点)大于插入点元素,单旋
            if(X < T -> Left -> Element){
                T = SingleRotateWithLeft(T);
            }else{
                T = DoubleRotateWithLeft(T);
            }
        }
    }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 = SingleRotateWithRight(T);
            }else{
                T = DoubleRotateWithRight(T);
            }
        }
    }

    //返回T的高度,T的两儿子树中最大高度 + 1
    T -> Height = Max(Height(T -> Left),Height(T -> Right)) + 1;
    return T;
}

AvlTree Delete(ElementType X,AvlTree T)
{
    Position temp;
    if(T == NULL){
        // 元素未找到异常
    }else if(X < T -> Element){
        T -> Left = Delete(X,T -> Left);
        // 判断目标节点是否不平衡
        if(Height(T -> Right) - Height(T -> Left) == 2){
            /* 若不平衡,则比较目标节点(T节点)的右节点的,左、右儿子树的高度 */
            /* 若右儿子树高度大于左儿子树高度,单旋操作 */
            /* 若左儿子树高度大于右儿子树高度,双旋操作 */
            /* 若左、右儿子树高度相等,单旋、双旋都可(默认单旋)*/
            if(Height(T -> Right -> Right) < Height(T -> Right -> Left) ){
                T = DoubleRotateWithRight(T);
            }else{
                T = SingleRotateWithRight(T);
            }
        }

    }else if(X > T -> Element){
        T -> Right = Delete(X,T -> Right);
        // 判断目标节点是否不平衡
        if(Height(T -> Left) - Height(T -> Right) == 2){
            if(Height(T -> Left -> Right) > Height(T -> Left -> Left) ){
                T = DoubleRotateWithLeft(T);
            }else{
                T = SingleRotateWithLeft(T);
            }
        }
    }else if((T -> Left != NULL) && (T -> Right != NULL)){
        /* 目标节点匹配到元素X,且有两个儿子树 */

        //找到目标节点右子树的最小节点
        temp = FindMin(T -> Right);
        //最小节点的元素覆盖目标节点元素
        T -> Element = temp -> Element;
        //递归调用,删除右子树中的最小节点
        T -> Right = Delete(T -> Element,T -> Right);
        // 判断目标节点是否不平衡
        if(Height(T -> Left) - Height(T -> Right) == 2){
            if(Height(T -> Left -> Right) > Height(T -> Left -> Left) ){
                T = DoubleRotateWithLeft(T);
            }else{
                T = SingleRotateWithLeft(T);
            }
        }
    }else{
        /* 目标节点匹配到元素X,且有一个儿子树,或没有儿子树 */
        /* 目标节点最多只有一个儿子树,因此左子树高度为-1,右子树高度必为0 */
        /* 所以该目标节点处,不会发生不平衡情况 */

        temp = T;
        if(T -> Left == NULL){
            T = T -> Right;
        }else if(T -> Right == NULL){
            T = T -> Left;
        }
        free(temp);
    }
    // 计算高度
    T -> Height = Max(Height(T -> Left),Height(T -> Right)) + 1;
    return T;
}

ElementType Retrieve(Position P)
{
    if(P!=NULL)
    return P->Element;
    else return -1;
}

int main()
{
    system("pause");
    return 0;
}

伸展树(自顶而下)

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
 
typedef struct SplayNode *SplayTree;
typedef SplayTree Position;
typedef int ElementType;
 
struct SplayNode
{
	ElementType data;
	Position left;
	Position right;
};

static Position NullNode;
 
SplayTree InitTree();
SplayTree Splaying(SplayTree T, ElementType x);
SplayTree LLRotate(SplayTree K);
SplayTree RRRotate(SplayTree K);
SplayTree FindMax(SplayTree T);
SplayTree FindMin(SplayTree T);
SplayTree Insert(ElementType x, SplayTree T);
SplayTree Delete(ElementType x, SplayTree T);
void Traversal(SplayTree T);
void Traversal(SplayTree T,int i);

SplayTree InitTree()						//初始化树,将NullNode看做NULL指针,避免了检测空树
{
	if (NullNode == NULL)
	{
		NullNode = (SplayTree)malloc(sizeof(SplayNode));
		if (NULL == NullNode)
		{
			printf("error,memery is full");
		}
		//该节点的左子树和右子树指向该节点本身。
		NullNode->left = NullNode->right = NullNode;
	}
	return NullNode;
}
 
SplayTree Splaying(SplayTree T, ElementType x)
{
	//带有左指针和右指针的头结点包含了左子树和右子树的根
	struct SplayNode Header;
	Header.left = Header.right = NullNode;
 
	Position LeftTreeMax, RightTreeMin;
	LeftTreeMax = RightTreeMin = &Header;
 
	NullNode->data = x;		//这里NullNode的数据域是x
	//当查找到NullNode时或者是找到了x时,循环结束
	while (x != T->data)
	{
		if (x < T->data)
		{
			if (x < T->left->data)
			{
				T = LLRotate(T);
			}
			if (NullNode == T->left)		//左子树为空
			{
				break;
			}
			RightTreeMin->left = T;
			RightTreeMin = T;
			//只要第一次左子树变为非空,那么T = T->left将会使LeftTreeMax在初始化后不再改变
			T = T->left;
			//这样的话LeftTreeMax将仍然指向Header,它将包含右子树的根
		}
		else
		{
			if (x > T->right->data)
			{
				T = RRRotate(T);
			}
			if (NullNode == T->right)		//右子树为空
			{
				break;
			}
			LeftTreeMax->right = T;
			LeftTreeMax = T;
			//只要第一次右子树变为非空,那么T = T->right将会使RightTreeMin在初始化后不再改变
			T = T->right;
		}
	}
	//连接
	LeftTreeMax->right = T->left;		
	RightTreeMin->left = T->right;		
	T->left = Header.right;		
	T->right = Header.left;
 
	return T;
}
 
SplayTree LLRotate(SplayTree K)
{
	Position M;
	M = K->left;
	K->left = M->right;
	M->right = K;
 
	return M;
}
 
SplayTree RRRotate(SplayTree K)
{
	Position M;
	M = K->right;
	K->right = M->left;
	M->left = K;
 
	return M;
}
 
SplayTree FindMax(SplayTree T)
{
	T = Splaying(T, INT_MAX);	//最大值处展开
	return T;
}
 
SplayTree FindMin(SplayTree T)
{
	T = Splaying(T, INT_MIN);	//最小值处展开
	return T;
}
 
SplayTree Insert(ElementType x, SplayTree T)
{
	SplayTree NewNode;
	NewNode = (SplayTree)malloc(sizeof(SplayNode));
	if (NewNode == NULL)
		printf("error ,memory is full");
	NewNode->data = x;
 
	if (T == NullNode)		//T是空的情形
	{
		NewNode->left = NewNode->right = NullNode;
		T = NewNode;
	}
	else 
	{
		T = Splaying(T, x);		//伸展
 
		if (x < T->data) 
		{
			NewNode->left = T->left;
			NewNode->right = T;
			T->left = NullNode;
			T = NewNode;
		}
		else if (x > T->data)
		{
			NewNode->right = T->right;
			NewNode->left = T;
			T->right = NullNode;
			T = NewNode;
		}
		else if (x == T->data) 
		{
			/* 重复值不做插入 */
			free(NewNode);
		}
	}
	return T;
}
 
SplayTree Delete(ElementType x, SplayTree T)
{
	Position newnode;
	if (T != NullNode)
	{
		T = Splaying(T, x);
		if (x == T->data)	//找得到该元素
		{
			if (T->left == NullNode)		//左子树为空
			{
				newnode = T->right;			//根就是该节点的右子树
			}
			else
			{
				newnode = T->left;			//该节点的左子树成为新根
				newnode = Splaying(newnode, x);	//x作为展开点,那么这个伸展操作将会把最大的节点提升至根处
				//那么这个根节点没有右子树(右子树为空)  
				newnode->right = T->right;	//将原来的右子树挂上
			}
			free(T);
			T = newnode;	//newnode作为新的根节点
		}
	}
	return T;
}
 
void Traversal(SplayTree T)		//中序遍历
{
	if (NullNode != T)
	{
		Traversal(T->left);
		printf("%d ", T->data);
		Traversal(T->right);
	}
}
 
void Traversal(SplayTree T, int i)	//前序遍历
{
	if (NullNode != T)
	{
		printf("%d ", T->data);
		Traversal(T->left, 1);
		Traversal(T->right, 1);
	}
}


int main()
{
	SplayTree T = InitTree();
	T = Insert(7, T);
	T = Insert(6, T);
	T = Insert(5, T);   
	T = Insert(4, T);
	T = Insert(3, T);
	T = Insert(2, T);
	T = Insert(1, T);
	T = Insert(0, T);
	printf("前序遍历输出结果:");
	Traversal(T, 1);
	printf("\n");
	printf("中序遍历输出结果:");
	Traversal(T);
	printf("\n");
	T = Delete(4, T);
	printf("删除4以后前序遍历输出结果:");
	Traversal(T, 1);
	printf("\n");
	printf("中序遍历输出结果:");
	Traversal(T);
	printf("\n");
	printf("树中最小值是:%d\n",FindMin(T)->data);
	printf("树中最大值是:%d\n", FindMax(T)->data);
	system("pause");
	return 0;
}

伸展树(自下而上)

#include<stdio.h>
#include<stdlib.h>
//伸展树的实现 

typedef struct splayNode {
	int element;
	struct splayNode* left;
	struct splayNode* right;
}*SplayTree;

SplayTree SingleTotateWithLeft(SplayTree T);
SplayTree SingleTotateWithRight(SplayTree T);
SplayTree DoubleTotateWithLeft(SplayTree T);
SplayTree DoubleTotateWithRight(SplayTree T);
SplayTree splaying(SplayTree Root, SplayTree T, SplayTree P);
void print(SplayTree T);
 
void print(SplayTree T) {
	//中序 
	if (T->left != NULL) {
		print(T->left);
	}
	printf("%d ", T->element);
	if (T->right != NULL) {
		print(T->right);
	}
}

void print2(SplayTree T) {
	//前序 根左右
	printf("%d ", T->element);
	if (T->left != NULL) {
		print2(T->left);
	}
	if (T->right != NULL) {
		print2(T->right);
	}
}
 
SplayTree insert(int X, SplayTree T) {
	if (T == NULL) {
		//树为空
		T = (SplayTree)malloc(sizeof(struct splayNode));
		T->element = X;
		T->left = T->right = NULL;
	}
	else {
		//不空
		if (X > T->element) {
			//往右子树走
			T->right = insert(X, T->right);
		}
		else if (X < T->element) {
			//往左子树走
			T->left = insert(X, T->left);
		}
	}
	return T;
}
//查找
SplayTree find(int X, SplayTree T) {
	if (T == NULL) {
		printf("tree is NULL");
		return NULL;
	}
	else {
		SplayTree P = T;
		while (P) {
			if (X > P->element) {
				//在右子树中
				P = P->right;
			}
			else if (X < P->element) {
				//在左子树中
				P = P->left;
			}
			else if (X == P->element) {
				//找到了
				//开始调整伸展树
				T = splaying(T, T, P);
				return T;
			}
		}
		return NULL;
	}
}

SplayTree splaying(SplayTree Root, SplayTree T, SplayTree P) {
	if (P->element > T->element) {
		//比T大 往右走
		T->right = splaying(Root, T->right, P);
	}
	else if (P->element < T->element) {
		//比T小 往左走
		T->left = splaying(Root, T->left, P);
	}
 
 
	//三种情况
	//1要查找的结点为根结点的左右孩子 zig 
	if (Root->left != NULL && Root->left == P) {
		//是根的左孩子,实行左旋
		Root = SingleTotateWithLeft(Root);
		return Root;
	}
	else if (Root->right != NULL && Root->right == P) {
		//是根的右孩子,实行右旋
		Root = SingleTotateWithRight(Root);
		return Root;
	}
	//第二种情况  zig-zag
	if (T->left != NULL && T->left != P && T->left->right != NULL && T->left->right == P) {
		//先右旋 后左旋 即左双旋
		T = DoubleTotateWithLeft(T);
	}
	else if (T->right != NULL && T->right != P && T->right->left != NULL && T->right->left == P) {
		//先左旋 后右旋 即右双旋
		T = DoubleTotateWithRight(T);
	}
	//第三种情况 zig-zig
	if (T->left != NULL && T->left != P && T->left->left != NULL && T->left->left == P) {
		//先左旋 再左旋
		T = SingleTotateWithLeft(T);
		T = SingleTotateWithLeft(T);
	}
	else if (T->right != NULL && T->right != P && T->right->right != NULL && T->right->right == P) {
		//先右旋 再右旋
		T = SingleTotateWithRight(T);
		T = SingleTotateWithRight(T);
	}
 
	return T;
}
//左单旋
SplayTree SingleTotateWithLeft(SplayTree T) {
	SplayTree M;
	M = T->left;
	T->left = M->right;
	M->right = T;
 
	return M;
}
//右单旋
SplayTree SingleTotateWithRight(SplayTree T) {
	SplayTree M;
	M = T->right;
	T->right = M->left;
	M->left = T;
 
	return M;
}
//左双旋
SplayTree  DoubleTotateWithLeft(SplayTree T) {
	//先进行右旋 再进行左旋
	T->left = SingleTotateWithRight(T->left);
	return SingleTotateWithLeft(T);
}
//右双旋
SplayTree DoubleTotateWithRight(SplayTree T) {
	//先进行左旋,再进行右旋
	T->right = SingleTotateWithLeft(T->right);
	return SingleTotateWithRight(T);
}
 
 
int main() {
	//测试
	SplayTree T = NULL;
	T = insert(7, T);
	T = insert(6, T);
	T = insert(5, T);
	T = insert(4, T);
	T = insert(3, T);
	T = insert(2, T);
	T = insert(1, T);
 
	print2(T);
 
	T = find(1, T);
	printf("查找后:");
	print2(T);
	T = find(2, T);
	T = find(5, T);
	printf("再次查找后:");
	print2(T);
 
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青云遮夜雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值