建立完全搜索二叉树(Complete Binary Search Tree )(c++)

Complete Binary Search Tree(c++)

本题目来自 PTA的,Complete Binary Search Tree
题目详细信息本文不再给出,可以点击以上链接。

因为题目要求,首先输入二叉树的结点个数,再输入每个结点对应的值,建立二叉树,既是二叉搜索树,又是完全二叉树

整体思路

  1. 根据输入的结点数,建立完全二叉树;
  2. 将节点数值放在数组中,从小到大排序;
  3. 根据根左儿子的结点数(左儿子的值都比根的值小,右儿子的值都比根的值大,所以,例如左儿子有6个结点,则根的值为数组中第7大的值),选取数组中对应的值,放入其中,然后更新左儿子数组,右儿子数组,递归将值放入其中。

代码如下

#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): 层次遍历函数,根据层次遍历的方法,将二叉树数据按顺序存入数组中,输入为二叉树根的地址和二叉树元素个数,层次遍历顺序的数组。

你可能感兴趣的:(数据结构)