本题目来自 PTA的,Complete Binary Search Tree
题目详细信息本文不再给出,可以点击以上链接。
因为题目要求,首先输入二叉树的结点个数,再输入每个结点对应的值,建立二叉树,既是二叉搜索树,又是完全二叉树。
#include
#define MAXSIZE 2000
using namespace std;
typedef struct LNode* List;
struct LNode
{
int data;
List left;
List right;
};
List BuideTree(int); //构建具有num个元素的完全二叉树
int* Sort(int[], int); //将数组num[]按从小到大排序
List FindFirstNullPosition(List); //顺序找到第一个空位置
int FindNumberOfTree(List); //计算树的结点数
List PutNumInTree(List, int[], int); //将数据放入结点中
int* SortNum(int[], int, int, int); //截取数组的一部分
int* LevelorderTraversal(List, int); //层次排列
int main()
{
int numOfElements, num;
cin >> numOfElements; //树的结点数
int nums[numOfElements];
for (int i = 0; i < numOfElements; ++i) //将数结点的数值放入数组
{
cin >> num;
nums[i] = num;
}
int* ptrNum, *ptrTest, *numQueue;
List tree;
tree = BuideTree(numOfElements); //建立完全二叉树
ptrNum = Sort(nums, numOfElements); //数组从小到大排序
tree = PutNumInTree(tree,ptrNum,numOfElements); //将有序数组放入建好的树
numQueue = LevelorderTraversal(tree, numOfElements); //层次遍历,将结点数据放入数组
for (int i = 0; i < numOfElements-1; ++i) //将数组元素输出
{
cout << numQueue[i] << " ";
}
cout << numQueue[numOfElements-1] << endl;
return 0;
}
/**构建具有num个元素的完全二叉树*/
List BuideTree(int numOfElements )
{
List ptrInit;
if (numOfElements)
{
List T, temp;
T = new LNode //创建第一个节点
T->left = 0;
T->right = 0;
ptrInit = T;
for (int i = 0; i < numOfElements-1; ++i) //创建接下来的 numOfElements-1 个节点
{
List T, temp;
T = new LNode;
T->left = 0;
T->right = 0;
temp = FindFirstNullPosition(ptrInit); //返回第一个有空子树的结点地址
if (!temp->left)
{
temp->left = T;
}
else if (!temp->right)
{
temp->right = T;
}
}
}
return ptrInit;
}
/**查找第一个空位置*/
List FindFirstNullPosition(List tree)
{
List midTree = tree; //类似层次遍历的思想
List ptrQueue[MAXSIZE];
int flagIn = -1, flagOut = -1;
if (tree)
{
++flagIn; //放入第一个
ptrQueue[flagIn] = tree;
while (flagIn > flagOut)
{
++flagOut; //抛出一个
midTree = ptrQueue[flagOut];
if (midTree->left && midTree->right)
{
++flagIn; //放入左子树指针
ptrQueue[flagIn] = midTree->left;
++flagIn; //放入右子树指针
ptrQueue[flagIn] = midTree->right;
}
else
{
break;
}
}
return midTree;
}
else
{
return tree;
}
}
/**统计树的结点数*/
int FindNumberOfTree(List tree)
{
int numOfTree = 0, numOfLeftTree = 0, numOfRightTree = 0;
if (tree)
{
numOfLeftTree = FindNumberOfTree(tree->left);
numOfRightTree = FindNumberOfTree(tree->right);
numOfTree = numOfLeftTree + numOfRightTree;
return numOfTree + 1;
}
else
{
return 0;
}
}
/**将数组从小到大排序*/
int* Sort(int ptrNums[], int numOfElements)
{
//本次采用冒泡排序
int temp;
for (int i = 0; i < numOfElements-1; ++i)
{
for (int j = 0; j < numOfElements-1-i; ++j)
{
if (ptrNums[j] > ptrNums[j+1])
{
temp = ptrNums[j];
ptrNums[j] = ptrNums[j+1];
ptrNums[j+1] = temp;
}
}
}
return ptrNums;
}
/**取数组中连续的num个数*/
int* SortNum(int ptrNums[], int numOfElements, int num, int flag) //flag = 1,从0取;flag = 0,从end取
{
int *nums;
nums = new int[num];
if (flag)
{
for (int i = 0; i < num; ++i)
{
nums[i] = ptrNums[i];
}
}
else
{
for (int i = 0; i < num ; ++i)
{
nums[i] = ptrNums[numOfElements-num+i];
}
}
return nums;
}
/**将数字放到树中*/
List PutNumInTree(List tree, int ptrNums[], int numOfElements)
{
if (tree)
{
int numOfLeftTree = 0, numOfRightTree = 0;
numOfLeftTree = FindNumberOfTree(tree->left); //树左子树元素个数
numOfRightTree = FindNumberOfTree(tree->right); //树的右子树元素个数
tree->data = ptrNums[numOfLeftTree]; //对当前树根赋值
int* numOfLeft, *numOfRight;
numOfLeft = SortNum(ptrNums, numOfElements, numOfLeftTree, 1);
numOfRight = SortNum(ptrNums, numOfElements, numOfRightTree, 0);
PutNumInTree(tree->left, numOfLeft, numOfLeftTree); //递归左儿子
PutNumInTree(tree->right, numOfRight, numOfRightTree); //递归右儿子
}
return tree;
}
/**遍历输出*/
int* LevelorderTraversal( List BT , int numOfElements)
{
int* numQueue, flagOfNum = 0;
numQueue = new int[numOfElements];
int sequence[2000] = {0};
List addrSequenc[2000] = {NULL};
int flagOut = 0, flagIn = 0;
if(!BT)
{
return 0;
}
sequence[flagIn] = BT->data;
addrSequenc[flagIn] = BT;
++flagIn;
while(flagOut != flagIn)
{
numQueue[flagOfNum++] = sequence[flagOut];
BT = addrSequenc[flagOut];
++flagOut;
if(BT->left)
{
sequence[flagIn] = BT->left->data;
addrSequenc[flagIn] = BT->left;
++flagIn;
}
if(BT->right)
{
sequence[flagIn] = BT->right->data;
addrSequenc[flagIn] = BT->right;
++flagIn;
}
}
return numQueue;
}
用到的函数
List BuideTree(int); //构建具有num个元素的完全二叉树
int* Sort(int[], int); //将数组num[]按从小到大排序
List FindFirstNullPosition(List); //顺序找到第一个空位置
int FindNumberOfTree(List); //计算树的结点数
List PutNumInTree(List, int[], int); //将数据放入结点中
int* SortNum(int[], int, int, int); //截取数组的一部分
int* LevelorderTraversal(List, int); //层次排列
List BuideTree(int numOfElements): 构建树的函数,根据输入的正整数,建立有numOfElements个结点的完全二叉树,过程中调用了FindFirstNullPosition() ,根据其返回的地址,判断是左儿子为空还是右儿子为空,注意要首先判断左儿子,若左儿子为空则不再判断右儿子,返回二叉树根的地址;
List FindFirstNullPosition(List): 被List BuideTree() 调用,在建树过程中,用层次遍历的方法,返回第一个有空儿子(左儿子或右儿子为NULL)的结点的地址;
int* Sort(int[], int): 因博主水平有限,仅用冒泡排序,将数组从小到大排列,输入为数组首地址和元素个数,返回数组首地址;
int FindNumberOfTree(List): 输入树的根的地址,返回二叉树中结点的个数,用于PutNumInTree() 函数中,计算左儿子和右儿子的结点数,并根据结点数划分左右儿子的数组,以及确定根的值,返回结点个数;
List PutNumInTree(List, int[], int): 将数组的值放入二叉树中,输入为完全二叉树根的地址,数组首地址和数组元素个数,返回即使完全二叉树又是二叉搜索树的二叉树;
int* SortNum(int[], int, int, int): 将数组截取一部分,输入为数组首地址,数组元素个数,要截取的元素个数,flag标志位,flag = 1时,数组开始位置向后复制,flag = 0时,数组从后向前复制,返回复制后数组的首地址;
int* LevelorderTraversal(List, int): 层次遍历函数,根据层次遍历的方法,将二叉树数据按顺序存入数组中,输入为二叉树根的地址和二叉树元素个数,层次遍历顺序的数组。