二叉树的遍历
来源:互联网 发布:dota2英雄知乎 编辑:程序博客网 时间:2024/06/04 18:42
摘要:本文讲解了如何使用C++实现了二叉树的创建,添加节点,删除节点,使用递归和非递归方法分别进行前中后遍历,进行层遍历
关键字 :二叉树遍历
- 二叉树的结构体
- 二叉树的建立
- 二叉树的递归遍历
- 前序遍历
- 中序遍历
- 后序遍历
- 删除节点
- 二叉树的非递归遍历
- 前序遍历
- 中序遍历
- 后序遍历
- 层序遍历
- 源代码
二叉树的结构体
typedef struct node{ int key, visited = 0; struct node *lChild, *rChild;}Node, *BST;
这里key是存储节点的值,visited用来辅助判断节点是否被访问,在递归后序遍历时用到。
二叉树的建立
// 建立BST void createBST(Node * &T, int a[], int n){ T = NULL; int i; for(i = 0; i < n; i++) { BSTInsert(T, a[i]); }}
T是根节点,a[]存储节点的值,n是节点的个数
其中BSTInsert(T, a[i])函数的实现如下:
// 在给定的BST中插入结点,其数据域为element, 使之称为新的BST bool BSTInsert(Node * &p, int element){ if(NULL == p) // 空树 { p = new Node; //p = (BST *)malloc(sizeof(BST)); p->key = element; p->lChild = p->rChild = NULL; return true; } if(element == p->key) // BST中不能有相等的值 return false; if(element < p->key) // 递归 return BSTInsert(p->lChild, element); return BSTInsert(p->rChild, element); // 递归 }
二叉树的递归遍历
前序遍历
// 先序遍历 void preOrderTraverse(BST T){ BST p = T; if(p) { cout << p->key << " "; preOrderTraverse(p->lChild); preOrderTraverse(p->rChild); }}
中序遍历
// 中序遍历 void midOrderTraverse(BST T){ if(T) { midOrderTraverse(T->lChild); cout << T->key << " "; midOrderTraverse(T->rChild); }}
后序遍历
// 后序遍历 void backOrderTraverse(BST T){ if(T) { backOrderTraverse(T->lChild); backOrderTraverse(T->rChild); cout << T->key << " "; }}
删除节点
//删除二叉树中与key值相等的节点bool DeleteBST(BST & T, int key){ /* 若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素节点 */ /* 并返回TRUE;否则返回FALSE */ if(!T) return false; /* 不存在关键字等于key的数据元素 */ else { if(key == T->key) Delete(T); else if(key < T->key) return DeleteBST(T->lChild, key); else return DeleteBST(T->rChild, key); }}
DeleteBST()的作用是寻找节点值和key值相等的节点,Delete(T)才是真正删除节点的函数。代码如下:
int Delete(BST & p){ /* 从二叉排序树中删除节点p, 并重接它的左或右子树 */ BST q, s; if(!p->lChild && !p->rChild) /* p为叶子节点 */ p = 0; else if(!p->lChild) /* 左子树为空,重接右子树 */ { q = p; p = p->rChild; free(q); } else if(!p->rChild) /* 右子树为空,重接左子树 */ { q = p; p = p->lChild; free(q); } else /* 左右子树均不为空 */ { q = p; s = p->lChild; while(s->rChild) /* 转左,然后向右走到尽头*/ { q = s; s = s->rChild; } p->key = s->key; if(q != p) /* 判断是否执行上述while循环 */ q->rChild = s->lChild; /* 执行上述while循环,重接右子树 */ else q->lChild = s->lChild; /* 未执行上述while循环,重接左子树 */ free(s); } return true;}
删除节点要遵循以下规则:
(1)删除节点为叶节点,直接删除;否则,执行步骤(2)
(2)当删除节点的右子树为空时,直接把左子树的根节点作为删除节点的左孩子;否则,执行步骤(3);
(3)当删除节点的左子树为空时,直接把右子树的根节点作为删除节点的右孩子;否则,执行步骤(4);
(4)当左子树和右子树都不为空时,设删除节点为p节点,先寻找p节点的左孩子,设为s节点,若s存在右孩子,执行步骤a;否则,执行步骤b;
a.以s节点为起始点,一直寻找s的最右端孩子,设为s节点,s节点的父节点设为q节点。此时把s的左子树作为q节点的右子树,s节点直接替代p节点;
b.p节点的右子树作为s节点的右子树,并且用s节点替换p节点。
步骤图解如下:
1.树的原图
2.执行规则(1)
删除叶子节点7,则直接删除
3.执行规则(2)
删除值为5的节点,由于该节点右子树为空,只需把节点5的左子树作为父节点6的左子树,然后删除节点5。
4.执行规则(3)
删除值为11的节点,由于该节点左子树为空,只需把节点11的右子树作为父节点10的右子树,然后删除节点11。
5.执行规则(4)a条例
删除值为10的节点,由于节点10的第一个左孩子6存在右子树,故寻找节点6的最右端孩子节点,为9,把节点9的左子树作为父节点6的右子树,并且以节点9替换要删除节点10,然后删除节点10。
6.执行规则(4)b条例
删除值为13的节点,由于节点13的第一个左孩子12不存在右子树,故把13的右子树作为12的右子树,以节点12替代节点13,删除节点13。
二叉树的非递归遍历
前序遍历
void preSearch(BST T){ stack<BST> s; BST p = T; while(p) { while(p) { cout << p->key << " "; s.push(p); p = p->lChild; } while(!s.empty() && !p) { p = s.top(); s.pop(); p = p->rChild; } }}
中序遍历
void midSearch(BST T){ BST p = T; stack<BST> s; while(p) { while(p) { s.push(p); p = p->lChild; } while(!s.empty() && !p) { p = s.top(); cout << p->key << " "; s.pop(); p = p->rChild; } //cout << p->key << " "; }}
后序遍历
void backSearch(BST T){ BST cur; BST pre = NULL; s.push(T); while(!s.empty()) { cur = s.top(); if((cur->lChild == NULL&&cur->rChild == NULL) || (pre != NULL && (pre == cur->lChild || pre == cur->rChild))) { cout << cur->key << " "; //如果当前结点没有孩子结点或者孩子节点都已被访问过 s.pop(); pre = cur; } else { if(cur->rChild != NULL) s.push(cur->rChild); if(cur->lChild != NULL) s.push(cur->lChild); } }}
层序遍历
void levelOrderTraverse(BST T){ BST p = T; if(p) { de.push_back(p); } while(!de.empty()) { p = de.front(); if(p->lChild) { de.push_back(p->lChild); } if(p->rChild) { de.push_back(p->rChild); } p = de.front(); cout << p->key << " "; de.pop_front(); }}
源代码
#include <iostream> #include <deque>#include <stack>using namespace std;// BST的结点 typedef struct node{ int key, visited = 0; struct node *lChild, *rChild;}Node, *BST;deque<BST> de;stack<BST> s;// 在给定的BST中插入结点,其数据域为element, 使之称为新的BST bool BSTInsert(Node * &p, int element){ if(NULL == p) // 空树 { p = new Node; //p = (BST *)malloc(sizeof(BST)); p->key = element; p->lChild = p->rChild = NULL; return true; } if(element == p->key) // BST中不能有相等的值 return false; if(element < p->key) // 递归 return BSTInsert(p->lChild, element); return BSTInsert(p->rChild, element); // 递归 }// 建立BST void createBST(Node * &T, int a[], int n){ T = NULL; int i; for(i = 0; i < n; i++) { BSTInsert(T, a[i]); }}#pragma region 递归// 先序遍历 void preOrderTraverse(BST T){ BST p = T; if(p) { cout << p->key << " "; preOrderTraverse(p->lChild); preOrderTraverse(p->rChild); }}// 中序遍历 void midOrderTraverse(BST T){ if(T) { midOrderTraverse(T->lChild); cout << T->key << " "; midOrderTraverse(T->rChild); }}// 后序遍历 void backOrderTraverse(BST T){ if(T) { backOrderTraverse(T->lChild); backOrderTraverse(T->rChild); cout << T->key << " "; }}int Delete(BST & p){ /* 从二叉排序树中删除节点p, 并重接它的左或右子树 */ BST q, s; if(!p->lChild && !p->rChild) /* p为叶子节点 */ p = 0; else if(!p->lChild) /* 左子树为空,重接右子树 */ { q = p; p = p->rChild; free(q); } else if(!p->rChild) /* 右子树为空,重接左子树 */ { q = p; p = p->lChild; free(q); } else /* 左右子树均不为空 */ { q = p; s = p->lChild; while(s->rChild) /* 转左,然后向右走到尽头*/ { q = s; s = s->rChild; } p->key = s->key; if(q != p) /* 判断是否执行上述while循环 */ q->rChild = s->lChild; /* 执行上述while循环,重接右子树 */ else q->lChild = s->lChild; /* 未执行上述while循环,重接左子树 */ free(s); } return true;}bool DeleteBST(BST & T, int key){ /* 若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素节点 */ /* 并返回TRUE;否则返回FALSE */ if(!T) return false; /* 不存在关键字等于key的数据元素 */ else { if(key == T->key) Delete(T); else if(key < T->key) return DeleteBST(T->lChild, key); else return DeleteBST(T->rChild, key); }}#pragma endregion#pragma region 非递归void levelOrderTraverse(BST T){ BST p = T; if(p) { de.push_back(p); } while(!de.empty()) { p = de.front(); if(p->lChild) { de.push_back(p->lChild); } if(p->rChild) { de.push_back(p->rChild); } p = de.front(); cout << p->key << " "; de.pop_front(); }}void preSearch(BST T){ stack<BST> s; BST p = T; while(p) { while(p) { cout << p->key << " "; s.push(p); p = p->lChild; } while(!s.empty() && !p) { p = s.top(); s.pop(); p = p->rChild; } }}void midSearch(BST T){ BST p = T; stack<BST> s; while(p) { while(p) { s.push(p); p = p->lChild; } while(!s.empty() && !p) { p = s.top(); cout << p->key << " "; s.pop(); p = p->rChild; } //cout << p->key << " "; }}void backSearch(BST T){ BST cur; BST pre = NULL; s.push(T); while(!s.empty()) { cur = s.top(); if((cur->lChild == NULL&&cur->rChild == NULL) || (pre != NULL && (pre == cur->lChild || pre == cur->rChild))) { cout << cur->key << " "; //如果当前结点没有孩子结点或者孩子节点都已被访问过 s.pop(); pre = cur; } else { if(cur->rChild != NULL) s.push(cur->rChild); if(cur->lChild != NULL) s.push(cur->lChild); } }}#pragma endregionint main(void){ int a[11] = { 10,6,11,5,9,13,4,8,12,14,7}; int n = 11; BST T; // 并非所有的a[]都能构造出BST,所以,最好对createBST的返回值进行判断 createBST(T, a, n); cout << "前序遍历:" << endl; preOrderTraverse(T); cout << endl; preSearch(T); cout << endl; cout << "中序遍历:" << endl; midOrderTraverse(T); cout << endl; midSearch(T); cout << endl; cout << "后序遍历:" << endl; backOrderTraverse(T); cout << endl; backSearch(T); cout << endl; //cout << DeleteBST(T,2) << endl; cout << "层序遍历:" << endl; levelOrderTraverse(T); cout << "删除2之后" << endl; DeleteBST(T, 2); levelOrderTraverse(T); cout << endl; return 0;}
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- AOP
- k-均值:一种基于型心的技术
- 动态添加权限
- SEO之外链发布方法
- Servlet+JSP 实现验证码
- 二叉树的遍历
- 替换字符串中的空格
- 【Android】使用UncaughtExceptionHandler捕获全局异常
- 深入理解ES6箭头函数中的this
- 学习淘淘商城第三十课(Jedis的使用)
- Android Shape常用
- ubuntu 12.04 搭建ftp
- java 动态代理 cglib记录
- python爬取糗事百科