二叉樹的非遞迴遍歷 (leetcode)
阿新 • • 發佈:2019-02-14
利用資料結構-棧,佇列, 加上相應思路等完成。
leetcode練習,隔段時間敲幾次程式碼
非遞迴先序
#include <cstdlib>
#include <iostream>
#include <stack>
using namespace std;
typedef struct node{
int data;
struct node *left, *right;
node(int _data = 0){
data = _data;
left = NULL;
right = NULL;
}
}Bnode;
Bnode* insert(Bnode* root, int data)
{
if (root == NULL)
root = new node(data);
else{
if (data < root->data)
root->left = insert(root->left, data);
else
root->right = insert(root->right, data);
}
return root;
}
/**非遞迴前序遍歷
*
* 每次取棧頂節點
* 再將其 右子樹 先入棧, 然後是 左子樹 入棧
* 這樣可以確保每次都是左子樹 比 右子樹先取出來
*/
void pre(Bnode* root)
{
stack<Bnode*> sta;
sta.push(root);
while (!sta.empty())
{
Bnode* top = sta.top();
sta.pop();
printf("%d\t", top->data);
if (top->right != NULL)
sta.push(top->right);
if (top->left != NULL)
sta.push(top->left);
}
}
int main()
{
int a[] = { 5, 3, 7, 1, 2, 6, 4 };
int n = 7;
int i;
Bnode *root = NULL;
for (i = 0; i < n; i++)
{
root = insert(root, a[i]);
}
/*
5
/ \
3 7
/ \ /
1 4 6
\
2
*/
pre(root);
return 0;
}
非遞迴中序
#include <cstdlib>
#include <iostream>
#include <stack>
using namespace std;
typedef struct node{
int data;
struct node *left, *right;
node(int _data = 0){
data = _data;
left = NULL;
right = NULL;
}
}Bnode;
Bnode* insert(Bnode* root, int data)
{
if (root == NULL)
root = new node(data);
else{
if (data < root->data)
root->left = insert(root->left, data);
else
root->right = insert(root->right, data);
}
return root;
}
/** 中序非遞迴
每次取棧頂
而棧的順序是 從根到最左,取出該節點列印並出棧
如果取出的節點沒有右子樹
則pLeft = pLeft->right;為NULL,下一次取出其父節點
如果右子樹不為空
則 pLeft = pLeft->right;後下一次會往棧中新增右子樹,但是根是在這之前入棧的
操作確保了一定是 左 根 右 的順序
*/
void inorder(Bnode* root)
{
stack<Bnode*> sta;
sta.push(root);
Bnode *pLeft = root->left;
while (!sta.empty() || pLeft != NULL) //注意這裡的判斷條件
{
while (pLeft != NULL) // 找到最左的節點
{
sta.push(pLeft);
pLeft = pLeft->left;
}
pLeft = sta.top(); //取棧頂
printf("%d\t", pLeft->data);
sta.pop();
pLeft = pLeft->right; // 轉向 右子樹
}
}
//void inorder(Bnode* root)
//{
// if (root != NULL)
// {
// inorder(root->left);
// printf("%d\t", root->data);
// inorder(root->right);
// }
//}
int main()
{
int a[] = { 5, 3, 7, 2, 1, 6, 4 };
int n = 7;
int i;
Bnode *root = NULL;
for (i = 0; i < n; i++)
{
root = insert(root, a[i]);
}
inorder(root);
return 0;
}
非遞迴後序
#include <cstdlib>
#include <iostream>
#include <stack>
using namespace std;
typedef struct node{
int data;
struct node *left, *right;
node(int _data = 0){
data = _data;
left = NULL;
right = NULL;
}
}Bnode;
Bnode* insert(Bnode* root, int data)
{
if (root == NULL)
root = new node(data);
else{
if (data < root->data)
root->left = insert(root->left, data);
else
root->right = insert(root->right, data);
}
return root;
}
/**
訪問根之前,要確保根的右子樹為空 或者 右子樹已經訪問過
否則要先把右子樹訪問到
*/
void postorder(Bnode* root)
{
stack<Bnode*> sta;
sta.push(root);
Bnode* preVisist = NULL;
Bnode* pLeft = root->left;
while (!sta.empty() || pLeft != NULL)
{
while (pLeft != NULL)
{
sta.push(pLeft);
pLeft = pLeft->left;
}
Bnode* top = sta.top();
if (top->right == NULL || preVisist == top->right) // 右子數為空 或者 右子數已經訪問過,再訪問根
{
printf("%d\n", top->data);
sta.pop();
preVisist = top;
pLeft = NULL;
}
else{
pLeft = top->right;
}
}// while
}
int main()
{
int a[] = { 5, 3, 7, 1, 2, 6, 4 };
int n = 7;
int i;
Bnode *root = NULL;
for (i = 0; i < n; i++)
{
root = insert(root, a[i]);
}
postorder(root);
return 0;
}
使用二叉樹非遞迴遍歷的一些題目
230. Kth Smallest Element in a BST
ac程式碼如下;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
if (root == NULL)
return 0;
stack<TreeNode*> sta;
sta.push(root);
TreeNode* pLeft = root->left;
int outTh = 1;
while (!sta.empty() || pLeft != NULL)
{
while (pLeft != NULL)
{
sta.push(pLeft);
pLeft = pLeft->left;
}
TreeNode* top = sta.top();
sta.pop();
if (outTh == k)
{
return top->val;
}
outTh++;
//cout << top->val;
if (top->right != NULL)
pLeft = top->right;
}
return 0;
}
};
114. Flatten Binary Tree to Linked List
For example,
Given
1
/ \
2 5
/ \ \
3 4 6
The flattened tree should look like:
1
\
2
\
3
\
4
\
5
\
6
採用非遞迴的先序遍歷,逐個節點設定
ac程式碼如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void flatten(TreeNode* root) {
if (root == NULL)
return;
stack<TreeNode*> sta;
sta.push(root);
TreeNode* lastNode = NULL;
while (!sta.empty())
{
TreeNode* top = sta.top();
sta.pop();
if (top->right != NULL)
sta.push(top->right);
if (top->left != NULL)
sta.push(top->left);
if (lastNode != NULL){
lastNode->left = NULL;
lastNode->right = top;
}
lastNode = top;
}
return;
}
};
採用遞迴方法求解的ac程式碼如下, 需要判斷仔細,考慮各種情況
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void dfs(TreeNode* root)
{
if (root == NULL)
return;
else if (root->left == NULL && root->right == NULL)
return;
else if (root->left != NULL && root->right == NULL){
TreeNode* rootL = root->left;
dfs(rootL);
root->left = NULL;
root->right = rootL;
return;
}
else if (root->left == NULL && root->right != NULL)
{
TreeNode* rootR = root->right;
dfs(rootR);
root->right = rootR;
return ;
}
else{
TreeNode* rootL = root->left;
TreeNode* rootR = root->right;
dfs(rootL);
dfs(rootR);
root->right = rootL;
root->left = NULL;
TreeNode* pre = NULL;
TreeNode* t = rootL;
while (t != NULL){
pre = t;
t = t->right;
}
pre->right = rootR;
}
}
void flatten(TreeNode* root) {
if (root == NULL)
return;
dfs(root);
return;
}
};