赞
踩
用的是和老师讲解的思路,先按照第一个输入次序建立一棵二叉搜索树,之后将其余输入序列依次读入,用Judge函数将其与建好的二叉搜索树进行判别,不建立实际的树。具体代码如下:
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define ElementType_Tree int /*树结点定义*/ typedef struct TreeNode* BinTree; struct TreeNode { ElementType_Tree Data; BinTree Left; BinTree Right; int flag; //结点是否被访问过的标签 }; BinTree MakeTree(int N); bool Judge(BinTree BST,int N); void Reset(BinTree BST); void FreeTree(BinTree BST); BinTree NewTreeNode(ElementType_Tree X); BinTree Insert(BinTree BST,ElementType_Tree X); bool check(BinTree BST,ElementType_Tree num); int main(void) { int N,L; //N:树的结点数;L:要检查的输入序列数 scanf("%d",&N); while (N) { scanf("%d",&L); BinTree BST=MakeTree(N); //建树 for (int i=0;i<L;i++) { if (Judge(BST,N)) //读入一个输入序列并进行判别 printf("Yes\n"); else printf("No\n"); Reset(BST); //将树的结点全部重新标记为未访问 } FreeTree(BST); //当前二叉搜索树已经全部判别完,释放这棵树 scanf("%d",&N); } return 0; } BinTree MakeTree(int N) /*建立二叉搜索树函数*/ { BinTree BST; ElementType_Tree X; scanf("%d",&X); //读入结点数据 BST=NewTreeNode(X); //申请一个树结点的空间并装填数据 for (int i=1;i<N;i++) { //依次插入其余结点 scanf("%d",&X); BST=Insert(BST,X); } return BST; } bool Judge(BinTree BST,int N) /*判别是否是同一二叉搜索树函数*/ { bool flag=true; ElementType_Tree num; scanf("%d",&num); //读入根结点 if (num!=BST->Data) //判别根结点是否一致 flag=false; //注意不能直接return,因为还要判别下一组数据 else BST->flag=1; for (int i=1;i<N;i++) { //依次判别其他结点 scanf("%d",&num); if (flag && !check(BST,num)) //如果根结点相同,则继续检查 flag=false; } if (flag) //全部读完一组数据后再返回结果 return true; else return false; } void Reset(BinTree BST) /*重置flag值的函数*/ { if (BST->Left) Reset(BST->Left); if (BST->Right) Reset(BST->Right); BST->flag=0; } void FreeTree(BinTree BST) /*释放树的函数*/ { if (BST->Left) FreeTree(BST->Left); if (BST->Right) FreeTree(BST->Right); free(BST); } BinTree NewTreeNode(ElementType_Tree X) /*申请并装填树结点函数*/ { BinTree T=(BinTree)malloc(sizeof(struct TreeNode)); T->Data=X; T->Left=T->Right=NULL; T->flag=0; return T; } BinTree Insert(BinTree BST,ElementType_Tree X) /*插入树结点函数(按照二叉搜索树的方式)*/ { if (!BST) { //空树 BST=NewTreeNode(X); } else { //非空树,递归插入 if (X < BST->Data) BST->Left=Insert(BST->Left,X); else if (X > BST->Data) BST->Right=Insert(BST->Right,X); } return BST; } bool check(BinTree BST,ElementType_Tree num) /*检查树结点函数*/ { if (BST->flag) { //结点已经访问过 if (num < BST->Data) //沿左子树继续递归检查 return check(BST->Left,num); else if (num > BST->Data) //沿右子树继续递归检查 return check(BST->Right,num); return false; } else { //结点未访问,则待检查数据必须与该树结点数据一致 if (num == BST->Data) { BST->flag=1; return true; } else return false; } }
这个是二叉平衡树最基本的操作——调整一棵二叉搜索树为二叉平衡树,主要是单旋和双旋函数的设计,直接上代码:
#include <stdio.h> #include <stdlib.h> #define ElementType int typedef struct AVLNode* AVLTree; struct AVLNode { ElementType Data; AVLTree Left; AVLTree Right; int Height; }; AVLTree Insert(AVLTree T,ElementType X); /*插入函数*/ AVLTree SingleLeftRotation(AVLTree A); /*左单旋函数*/ AVLTree SingleRightRotation(AVLTree A); /*右单旋函数*/ AVLTree DoubleLeftRightRotation(AVLTree A); /*左-右双旋函数*/ AVLTree DoubleRightLeftRotation(AVLTree A); /*右-左双旋函数*/ int Max(int a,int b); int GetHeight(AVLTree T); int main(void) { int N; ElementType X; AVLTree T=NULL; scanf("%d",&N); for (int i=0;i<N;i++) { scanf("%d",&X); T=Insert(T,X); } printf("%d\n",T->Data); return 0; } AVLTree Insert(AVLTree T,ElementType X) { if (!T) { T=(AVLTree)malloc(sizeof(struct AVLNode)); T->Data=X; T->Left=T->Right=NULL; T->Height=1; } else { if (X < T->Data) { T->Left=Insert(T->Left,X); if (GetHeight(T->Left)-GetHeight(T->Right)==2) //需要左旋 if (X < T->Left->Data) T=SingleLeftRotation(T); //左单旋 else T=DoubleLeftRightRotation(T); //左右单旋 } else if (X > T->Data) { T->Right=Insert(T->Right,X); if (GetHeight(T->Left)-GetHeight(T->Right)==-2) //需要右旋 if (X > T->Right->Data) T=SingleRightRotation(T); //右单旋 else T=DoubleRightLeftRotation(T); //右左单旋 } } T->Height=Max(GetHeight(T->Left),GetHeight(T->Right))+1; //必须更新树的高度! return T; } AVLTree SingleLeftRotation(AVLTree A) { AVLTree B=A->Left; A->Left=B->Right; B->Right=A; A->Height=Max(GetHeight(A->Left),GetHeight(A->Right))+1; B->Height=Max(GetHeight(B->Left),A->Height)+1; //GetHeight(B->Right)==A->Height; return B; } AVLTree SingleRightRotation(AVLTree A) { AVLTree B=A->Right; A->Right=B->Left; B->Left=A; A->Height=Max(GetHeight(A->Left),GetHeight(A->Right))+1; B->Height=Max(GetHeight(B->Right),A->Height)+1; return B; } AVLTree DoubleLeftRightRotation(AVLTree A) { A->Left=SingleRightRotation(A->Left); return SingleLeftRotation(A); } AVLTree DoubleRightLeftRotation(AVLTree A) { A->Right=SingleLeftRotation(A->Right); return SingleRightRotation(A); } int Max(int a,int b) { return (a>b?a:b); } int GetHeight(AVLTree T) { if (!T) //一定要考虑空树的情况! return 0; else return T->Height; }
这道题目有一定难度,我是看了陈越老师的思路讲解后做出来的。题目要求将一个输入序列建立为完全二叉搜索树,所谓完全二叉搜索树的意思是:
也就是这棵树既是一棵二叉搜索树,也是一棵完全搜索树。
#include <stdio.h> #include <stdlib.h> #include <math.h> #define MaxN 1000 int A[MaxN],T[MaxN]; //A:存储输入数据;T:存储完全搜索二叉树 int compare(const void*a, const void*b); //辅助qsort函数 void BuildCBSTree(int ALeft, int ARight, int TRoot); int GetLeftLength(int n); int main(void) { int N; scanf("%d",&N); for (int i=0;i<N;i++) scanf("%d",&A[i]); qsort(A,N,sizeof(int),compare); //库函数,快速排序 BuildCBSTree(0,N-1,0); //核心算法,建立完全搜索二叉树 printf("%d",T[0]); //打印结果 for (int i=1;i<N;i++) printf(" %d",T[i]); printf("\n"); return 0; } int compare(const void*a, const void*b) { return *(int*)a-*(int*)b; } void BuildCBSTree(int ALeft, int ARight, int TRoot) /*构建完全搜索二叉树*/ { int n,L,TLeftRoot,TRightRoot; n=ARight-ALeft+1; //结点数 if (n==0) //结束递归的条件 return; L=GetLeftLength(n); //得到左子树的结点数 T[TRoot]=A[ALeft+L]; //根结点的值 TLeftRoot=TRoot*2+1; //左子树根结点位置 TRightRoot=TLeftRoot+1; //右子树根结点位置 BuildCBSTree(ALeft,ALeft+L-1,TLeftRoot); //递归构建左子树 BuildCBSTree(ALeft+L+1,ARight,TRightRoot); //递归构建右子树 } int GetLeftLength(int n) /*获取左子树的结点数*/ { int L,H,X; //L:左子树的结点数;H:树的高度;X:最低一层的结点数 /*以下式子经数学推导得来*/ H=log(n+1)/log(2); //log,pow函数参数和返回值均为double,此处进行了自动类型转换 X=n+1-pow(2,H); X=(X < pow(2,H-1))?X:pow(2,H-1); L=pow(2,H-1)-1+X; return L; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。