判断是否为BST

        递归的方法,用返回false的方法。中序遍历的想法很好,空间浪费。遍历的过程记录上一次的值进行比较。

//题目描述
//
//请实现一个函数,检查一棵二叉树是否为二叉查找树。
//给定树的根结点指针TreeNode* root,请返回一个bool,代表该树是否为二叉查找树。


#include<iostream>
using namespace std;
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
        val(x), left(NULL), right(NULL) {
    }
};


class Checker {
public:
    //先想到的是返回true的情况, //改为return true有错误。
    bool checkBST(TreeNode* root) {  
        // write code here
        if (root == NULL) return true;
        if (root->left && root->left->val > root->val)
            return false;
        if (root->left && root->left->right && root->left->right->val>root->val)
            return false;
        if (root->right && root->right->val < root->val)
            return false;
        if (root->right&&root->right->left&&root->right->left->val < root->val)
            return false;

        return checkBST(root->left) && checkBST(root->right);
    }
};

//
//《程序员面试金典》 代码详解:http ://blog.youkuaiyun.com/zdplife/article/category/5799903
//题目分析:
//<方法1>
//首先我们想到的是二叉树中序遍历后的结果是有序的,根据这个结果,我们可以中序遍历二叉树,并把遍历结果存放在一个数组里面,然后判断这个数组大小是否是有序数组,如果是有序数组,则是二叉查找树,否则就不是。
//这个方法的时间复杂度是O(N),但是空间复杂度比较高,需要浪费O(N)的存储空间。
//<方法2>
//其实在<方法1>的基础上,我们可以在中序遍历的同时,比较大小,每次记录下上次遍历过的元素的值,如果当前元素的值大于上次遍历元素的值,则接着遍历,否则返回false,因为这个记录是一个址传递,所以需要用到引用形参进行传递。
//这个方法的时间复杂度与<方法1>的时间复杂度相同,只是空间复杂度只需要一个元素O(1)。
class Checker {
public:
    bool checkBST(TreeNode* root) {
        // write code here
        int min = INT_MIN;
        return inOrderCompare(root, min);
    }
    bool inOrderCompare(TreeNode* root, int &last)
    {
        if (root == NULL)
            return true;
        if (!inOrderCompare(root->left, last))
            return false;
        if (root->val < last)
            return false;
        last = root->val;
        if (!inOrderCompare(root->right, last))
            return false;
        return true;
    }
};
//<方法3>
//可以根据二叉查找树的定义来判断,二叉树的定义,所有左子树的节点小于根节点,所有右子树的节点大于根节点,并且左右子树也是二叉查找树。所以在递归的过程中,我们只需要传递两个参数(当前根节点对应的二叉树的所有节点的最大值和最小值),
//同时不断的更新这两个参数,如果当前节点的值不在这两个数范围中,则直接返回false,否则接着递归便可。




//非递归遍历二叉树,然后判断结果是否递增
#include <stack>
#include <vector>
class Checker {
public:
    bool checkBST(TreeNode* root) {
        // write code here
        stack<TreeNode*> s;
        TreeNode *pNode = root;
        vector<int> data;
        while (pNode != NULL || !s.empty())
        {
            while (pNode != NULL)
            {
                s.push(pNode);
                pNode = pNode->left;
            }
            if (!s.empty())
            {
                pNode = s.top();
                data.push_back(pNode->val);
                s.pop();
                pNode = pNode->right;
            }
        }
        for (size_t i = 0; i < data.size() - 1; i++)
        {
            if (data[i] > data[i + 1])
                return false;
        }
        return true;
    }
};

//首先利用中序遍历排序,其次遍历检查排序序列是否递增,最后输出结果!
class Checker {
public:
    vector<int> res;
    bool checkBST(TreeNode* root) {
        // write code here
        if (root == NULL) return true;
        bool flag = false;
        inorder(root);
        for (int i = 0; i<res.size() - 1; i++)
        {
            if (res[i]>res[i + 1])
            {
                flag = true;
                break;
            }
        }
        if (flag)
            return false;
        else
            return true;
    }
    void inorder(TreeNode* root){
        if (root == NULL) return;
        inorder(root->left);
        res.push_back(root->val);
        inorder(root->right);
    }
};

 

### C语言中常见数据结构的空间复杂度分析 #### 数组 数组是一种线性的数据结构,在内存中占据连续的存储单元。对于一维数组 `int arr[N]`,其空间复杂度为 O(N),因为需要分配 N 个整型变量的空间[^1]。 当涉及到多维数组时,例如二维数组 `int matrix[M][N]`,则会占用 M×N 的空间来保存所有的元素值,因此该情况下空间复杂度为 O(M*N)[^3]。 ```c // 定义一个M行N列的矩阵 int matrix[M][N]; ``` #### 链表 链表由一系列节点组成,每个节点包含两部分:一部分用于存储实际的数据项;另一部分是指向下一个节点地址的指针字段。单项链表中的每一个结点除了要存放下一个结点的位置外还需要额外的一个单位用来存放指向下一结点的指针,故而如果只考虑有效载荷,则长度为n的单向链表所需的空间大约是O(n)【注意这里假设指针本身所占的空间可以忽略不计】[^2]。 ```c struct Node { int data; struct Node* next; }; ``` #### 堆栈队列 堆栈(stack) 和队列(queue) 是两种特殊的线性表形式。它们可以通过数组或者链表实现。如果是基于固定大小的静态数组实现的话,那么无论何时都会保持固定的容量,即具有常数级别的空间开销 O(C); 而动态增长/缩减版本(如通过链表构建),则会在最坏的情况下达到输入规模的数量级 O(n)。 ```c #define MAX_SIZE 100 typedef struct Stack { int items[MAX_SIZE]; int top; }Stack; void push(Stack *s, int item){ s->items[++(s->top)] = item; } ``` #### 树形结构 树是由若干个称为顶点或节点的对象构成的一种层次化的非线性结构。二叉查找树(Binary Search Tree,BST),红黑树(Red Black Tree,RBTree)等都是典型的例子。一棵高度h含有n个内部节点的理想平衡二叉搜索树理论上最多只需要log₂(n+1)-1层高,所以理想状态下它的平均情况下的空间消耗也是接近于O(log n).但是请注意这并不意味着所有类型的树都遵循这样的规律——像完全不平衡的情况可能会退化成近乎链状的形式从而使得最大可能的高度变为n-1,进而导致更糟糕的空间性能表现. ```c struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; TreeNode* newNode(int value) { TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode)); node->val = value; node->left = NULL; node->right = NULL; return(node); } ``` #### 图 图(graph)是一类更为复杂的抽象模型,它既可以是有方向也可以是没有方向的关系网络。通常来说,邻接矩阵表示法下稠密图的空间需求较大约为V²(V代表顶点数目),而对于稀疏图而言采用邻接列表的方式能够显著减少不必要的零填充所带来的浪费,此时整体上仅需E+E'条边记录加V个头指针即可完成表达(E,E’分别对应无向图里的双向连接以及有向情形下单侧关联数量总和),也就是O(|V|+|E|)。 ```c #include <stdbool.h> bool adjMatrix[V][V]; // V is the number of vertices. ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值