二叉树

来源:互联网 发布:freebsd和centos 编辑:程序博客网 时间:2024/06/05 03:38

转自:http://blog.csdn.net/XTCGCH/article/details/70257831?locationNum=4&fps=1

摘要:本文讲解了如何使用C++实现了二叉树的创建,添加节点,删除节点,使用递归和非递归方法分别进行前中后遍历,进行层遍历

关键字 :二叉树遍历

    • 二叉树的结构体
    • 二叉树的建立
    • 二叉树的递归遍历
      • 前序遍历
      • 中序遍历
      • 后序遍历
      • 删除节点
    • 二叉树的非递归遍历
      • 前序遍历
      • 中序遍历
      • 后序遍历
      • 层序遍历
    • 源代码


二叉树的结构体

typedef struct node{    int key, visited = 0;    struct node *lChild, *rChild;}Node, *BST;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

这里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]);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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); // 递归  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

二叉树的递归遍历

前序遍历

// 先序遍历  void preOrderTraverse(BST T){    BST p = T;    if(p)    {        cout << p->key << " ";        preOrderTraverse(p->lChild);        preOrderTraverse(p->rChild);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

中序遍历

// 中序遍历  void midOrderTraverse(BST T){    if(T)    {        midOrderTraverse(T->lChild);        cout << T->key << " ";        midOrderTraverse(T->rChild);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

后序遍历

// 后序遍历  void backOrderTraverse(BST T){    if(T)    {        backOrderTraverse(T->lChild);        backOrderTraverse(T->rChild);        cout << T->key << " ";    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

删除节点

//删除二叉树中与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);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

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
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

删除节点要遵循以下规则: 
(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;        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

中序遍历

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 << " ";    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

后序遍历

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);        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

层序遍历

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();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

源代码

#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;}

原创粉丝点击