Tabla de contenido
1. La forma no recursiva realiza un recorrido de orden frontal-medio-posterior
1.1 Travesía de pedido anticipado
1.2 Recorrido posterior al pedido (usando dos pilas)
1.3 Operación de mostrar el recorrido posterior al pedido (usando una pila)
2. Realice el recorrido capa por capa del árbol binario
3. Cuente las capas con más árboles binarios
La estructura de un árbol binario:
class Node {
public:
Node(int v) {
value = v;
}
public:
int value;
Node* left;
Node* right;
};
1. La forma no recursiva realiza un recorrido de orden frontal-medio-posterior
1.1 Travesía de pedido anticipado
1. Imprima tan pronto como aparezca
2. Si hay un derecho, presione el derecho
3. Si la izquierda, presione la izquierda
void pre(Node* head) {
cout << "前序遍历:" << endl;
if (head != nullptr) {
stack<Node*> stack;
stack.push(head);
while (!stack.empty()) {
head = stack.top();
stack.pop();
cout << head->value << " ";
if (head->right != nullptr) {
stack.push(head->right);
}
if (head->left != nullptr) {
stack.push(head->left);
}
}
}
cout << endl;
}
1.2 Recorrido posterior al pedido (usando dos pilas)
¿Te resulta familiar el orden de la cabeza a la derecha a la izquierda ? Así es, ¿no es el recorrido en orden inverso?
1. Póngalo en la segunda pila res
2. Si la izquierda, presione la izquierda
3. Si hay un derecho, presione el derecho
4. Finalmente, imprima todo en res.
void pos(Node* head) {
cout << "后序遍历:" << endl;
if (head != nullptr) {
stack<Node*> st1;
stack<Node*> st2;
st1.push(head);
while (!st1.empty()) {
head = st1.top();
st1.pop();
st2.push(head);
if (head->left != nullptr) {
st1.push(head->left);
}
if (head->right != nullptr) {
st1.push(head->right);
}
}
while (!st2.empty()) {
cout << st2.top()->value << " ";
st2.pop();
}
}
cout << endl;
}
1.3 Operación de mostrar el recorrido posterior al pedido (usando una pila)
Solo use una pila para completar
void pos2(Node* h) {
cout<<"后序遍历炫技版: "<<endl;
if (h != nullptr) {
stack<Node*> stack;
stack.push(h);
Node* c = nullptr;
while (!stack.empty()) {
c = stack.top();
//说明这个c的左树都还没处理呢,肯定先要去处理左树
if (c->left != nullptr && h != c->left && h != c->right) {
stack.push(c->left);
}
//说明左树处理了,但右树没有处理,那就去处理右树
else if (c->right != nullptr && h != c->right) {
stack.push(c->right);
}
//左右树都处理完了,那就去处理头
else {
cout << stack.top()->value<<" ";
stack.pop();
h = c;//处理一个,那就让h记录刚处理的位置
}
}
}
cout << endl;
}
1.4 Recorrido en orden
1. Empuje todo el borde izquierdo en la pila en secuencia
2. 1 Si no se puede ejecutar, abre la pila y continúa la ejecución en el árbol derecho abierto
¿Por qué haces esto?
void in(Node* cur) {
cout<<"中序遍历 : "<<endl;
if (cur != nullptr) {
stack<Node*> stack;
while (!stack.empty() || cur != nullptr) {
if (cur != nullptr) {
stack.push(cur);
cur = cur->left;
}
else {
cur = stack.top();
stack.pop();
cout << cur->value << " ";
cur = cur->right;
}
}
}
cout << endl;
}
2. Realice el recorrido capa por capa del árbol binario
1. Usa la cola
Imprima cuando aparezca, avance al árbol de la izquierda, luego ingrese al árbol de la derecha
void level(Node* head) {
if (head == nullptr) {
return;
}
queue<Node*> queue;
queue.push(head);
while (!queue.empty()) {
Node* cur = queue.front();
cout << cur->value << " ";
queue.pop();
//System.out.println(cur.value);
if (cur->left != nullptr) {
queue.push(cur->left);
}
if (cur->right != nullptr) {
queue.push(cur->right);
}
}
}
También puede usar el método de la respuesta dada por Niuke: realizar la impresión en zigzag
vector<vector<int> > levelOrder(TreeNode* root) {
// write code here
vector<vector<int>> vt;
if(root==nullptr)
return vt;
//队列存储,进行层次遍历
queue<TreeNode*> q;
q.push(root);
TreeNode* cur;
while(!q.empty()){
vector<int> temp;
int n=q.size();
for(int i=0;i<n;++i){
cur=q.front();
q.pop();
temp.push_back(cur->val);
if(cur->left)
q.push(cur->left);
if(cur->right)
q.push(cur->right);
}
vt.push_back(temp);//一层都统计完之后再加入
}
return vt;
}
3. Cuente las capas con más árboles binarios
No solo para imprimir cada capa, sino también para descubrir dónde comienza o termina una capa
1. Usa el mapa
int maxWidthUseMap(Node* head) {
if (head == nullptr) {
return 0;
}
queue<Node*> queue;
queue.push(head);
// key 在 哪一层,value
unordered_map <Node*, int> levelMap;
levelMap.insert(make_pair(head,1));
int curLevel = 1; // 当前你正在统计哪一层的宽度
int curLevelNodes = 0; // 当前层curLevel层,宽度目前是多少
int Max = 0;
while (!queue.empty()) {
Node* cur = queue.front();
queue.pop();
int curNodeLevel = levelMap[cur];//当前的层数
if (cur->left != nullptr) {
levelMap.insert(make_pair(cur->left, curNodeLevel + 1));
queue.push(cur->left);
}
if (cur->right != nullptr) {
levelMap.insert(make_pair(cur->right, curNodeLevel + 1));
queue.push(cur->right);
}
if (curNodeLevel == curLevel) {
curLevelNodes++;
}
else {
Max = max(Max, curLevelNodes);
curLevel++;
curLevelNodes = 1;//刚开始的时候下一层肯定是1
}
}
Max = max(Max, curLevelNodes);
return Max;
}
2, sin mapa
int maxWidthNoMap(Node* head) {
if (head == nullptr) {
return 0;
}
queue<Node*> queue;
queue.push(head);
Node* curEnd = head; // 当前层,最右节点是谁
Node* nextEnd = nullptr; // 下一层,最右节点是谁
int Max = 0;
int curLevelNodes = 0; // 当前层的节点数
while (!queue.empty()) {
Node* cur = queue.front();
queue.pop();
if (cur->left != nullptr) {
queue.push(cur->left);
nextEnd = cur->left;
}
if (cur->right != nullptr) {
queue.push(cur->right);
nextEnd = cur->right;
}
curLevelNodes++;
if (cur == curEnd) {
Max = max(Max, curLevelNodes);
curLevelNodes = 0;
curEnd = nextEnd;
}
}
return Max;
}
Pregunta: dado un nodo en un árbol binario, devolver su nodo sucesor
El nodo sucesor se refiere al siguiente nodo atravesado por él para
1. Violencia:
La forma más sencilla es seguir buscando el nodo principal hasta que encuentre el nodo principal y luego atravesarlo para encontrar el siguiente nodo.
2. Ir directamente a su sucesor
Como es un recorrido en orden, debe seguir el orden de izquierda cabeza derecha,
Entonces, si un árbol tiene un subárbol derecho , su sucesor es directamente el subárbol más a la izquierda del subárbol derecho.
Si no hay un subárbol derecho , siga subiendo hasta que la relación padre-hijo sea que el subárbol es el subárbol izquierdo del padre (para el subárbol derecho, continúe subiendo)
Por supuesto, el último nodo no tiene sucesor, por lo que no debe encontrarse, así que simplemente devuelva nullptr
código:
Node* getSuccessorNode(Node* node) {
if (node == nullptr) {
return node;
}
if (node->right != nullptr) {
return getLeftMost(node->right);
}
else { // 无右子树
Node* parent = node->parent;
while (parent != nullptr && parent->right == node) { // 当前节点是其父亲节点右孩子
node = parent; // 那就继续向上去找
parent = node->parent;
}
return parent;
}
}
Node* getLeftMost(Node* node) {
if (node == nullptr) {
return node;
}
while (node->left != nullptr) {
node = node->left;
}
return node;
}
De la misma manera, buscar la tracción delantera es justo al revés.
Este árbol no existe en absoluto, pero lo simulé con recursividad.
El árbol claramente especificado se puede imprimir sin construir un árbol en absoluto