题目:
给定一个二叉搜索树的根节点 root
,和一个整数 k
,请你设计一个算法查找其中第 k
个最小元素(从 1 开始计数)。
预备知识:
二叉搜索树具有如下性质:
-
结点的左子树只包含小于当前结点的数。
-
结点的右子树只包含大于当前结点的数。
-
所有左子树和右子树自身必须也是二叉搜索树。
中序遍历
二叉树的中序遍历,采用递归调用函数的方式,按照访问左子树——根结点——右子树的方式遍历二叉树(LDR);在访问其左子树和右子树时,也按照同样的方式遍历;直到遍历完整棵树。
void inorder(bitree *p)
{
if(p!=NULL)
{
inorder(p->left);//中序遍历左子树
printf("%d",p->data);//访问根节点的数据域
inorder(p->right);//中序遍历右子树
}
}
思路及算法:
-
递归方式创建二叉树,该创建方式为从根结点开始逐个填满左子树再填右子树
例如要创建 3 则要输入31#2##4##
1 4
2
TreeNode *createBiTree(void) {//输入需要将二叉树补成满二叉树,输入空指针用#表示 char c; TreeNode *root; cin >> c; if (c=='#') root = nullptr;//当遇到#时,令树的根节点为空,从而结束该分支的递归 else { root = new TreeNode; root->data = c-48; root->left=createBiTree(); root->right=createBiTree(); } return root; }
-
中序遍历找到第k个最小元素
这里利用二叉搜索树的性质,结点的左子树只包含小于当前结点的数,即最左的根结点为最小的元素,结点的右子树只包含大于当前结点的数,即左子树<根<右子树,根据这个我们会惊喜地发现,第k个最小元素的k刚好等于完成访问的结点的数量,而中序遍历刚好符合这一要求,左子树->根节点->右子树,这样,中序遍历就是从最小的元素开始访问,每完成一个结点的访问,我们就用一个计数器count来记录访问次数,当访问到第k个元素时,count=k,即可输出该元素。
int res; void search(TreeNode* root,int &count,int k)//int &count,对参数的修改结果会带出来 { if(root == NULL||count>k) return ;//return用于直接结束函数 search(root->left,count,k);//中序遍历 int data= root->data; count++; if(count==k) { res=data; return; } search(root->right,count,k); } int kthSmallest(TreeNode* root, int k) { int count=0; search(root,count,k); return res; }
-
输出该元素