二叉树链式存储及其各种遍历和求深度、宽度(C语言实现、非递归)

定义二叉树结点、栈、队列

typedef struct TNode{ // 结点
    int data;
    struct TNode *lchild, *rchild;
}TNode, *BiTree;

typedef struct queen_node{  // 循环队列
    TNode *nodes[100];
    int front;  //指向队头元素的前一个(为了判别队空和判别队满)
    int size ; //指向队尾元素 
    int rear; // 尾进头出
}queen_node, *Queen;

typedef struct stack_node{ // 栈  头进头出。
    TNode *nodes[100];
    int top;  // top=-1为空栈
    int size;
}*Stack;
Stack init_Stack(){  // 初始化栈
    Stack stack = (Stack)malloc(sizeof(stack_node));
    stack->top = -1;
    stack->size = 100;
    return stack;
}
void push_stack(Stack S, TNode* p){ //入s栈
    if (S->top<S->size) {
        S->nodes[++S->top] = p;
    }
}
TNode* pop_stack(Stack s){ //出栈
    if (s->top!=-1) {
        return s->nodes[s->top--];
    }
    return NULL;
}


Queen init_queen(){
    Queen q = (Queen)malloc(sizeof(queen_node));
    q->front= -1;  //初始化 front指向队头前一个位置
    q->rear = -1;  // rear 指向队尾元素
    q->size = 100;
    return q;
}
void in_queen(Queen q, TNode* m){
    /**
     入队
     **/
    int a = (q->rear+1)%q->size;
    if (a != q->front){
         q->nodes[(++q->rear) % q->size] = m;
    }
}

TNode* out_queen(Queen q){// 出队
    if (q->front!=q->rear) {
      return q->nodes[(++q->front)%q->size];
    }else{
        return NULL;
    }
}


二叉树的创建

int CreateBiTree(BiTree &t)  // 结构体指针要修改必须用 & 表示是引用类型
{
    /**
    创建二叉树 链式存储法 中序依次输入结点 包括空节点
     **/
    int ch;
    scanf("%d", &ch);
    if (ch == 999){
        t = NULL;
        return -1;
    }
    else
    {
        t = (BiTree)malloc(sizeof(TNode));
        t->data = ch;
        CreateBiTree(t->lchild);
        CreateBiTree(t->rchild);
    }
    return 0;
}

void insertBiNode(BiTree &T, int number){
    /**
     插入单个结点  从左至右,从上至下
     **/
    if (T==NULL) {  //空树
        T = (BiTree)malloc(sizeof(TNode));
        T->data = number;
        T->lchild = NULL;
        T->rchild = NULL;
    }
    
    Queen q = init_queen();
    
    bool flag = false;
    TNode * p = T;
    TNode * temp;
    in_queen(q, p);
    while (q->front!=q->rear && flag==false) {
        p = out_queen(q);
        temp = (TNode*)(malloc(sizeof(TNode)));
        temp -> data = number;
        temp->lchild = NULL;
        temp ->rchild = NULL;
        if(p->lchild==NULL){
            p->lchild = temp;
            flag = true;
        }else if(p->rchild==NULL){
            p->rchild = temp;
            flag = true;
        }else{
            in_queen(q, p->lchild);
            in_queen(q, p->rchild);
        }
    }
}


先序遍历


int pre_bianli(BiTree T){ // 先序遍历
     int height = 0;  // 求树的深度
    
    
    Stack stack = init_Stack();  // 初始化空栈
    TNode* pre , *p;
    p = T; // 遍历指针
    pre = NULL; //上一个访问的结点
    while (stack->top!=-1 || p!=NULL) { // 栈不空或者遍历指针不空
        if(p!=NULL){
            std::cout<<p->data<<",";  // 先访问后入栈
            pre = p;  //记录最近访问结点
            push_stack(stack, p);
            p = p->lchild;
        }else{
            if(stack->top+1 > height){
                height = stack->top+1;
            }
            p = pop_stack(stack); //出栈
            if(p->rchild!=NULL && p->rchild!=pre){
                p = p ->rchild;
            }else{
                p = NULL;
            }
        }
        
    }
    return height;
}

中序遍历

int mid_bianli(BiTree T){ //中序遍历
    int height = 0;  // 求树的深度
    
    Stack stack = init_Stack();  // 初始化空栈
    TNode* pre , *p;
    p = T; // 遍历指针
    pre = NULL; //上一个访问的结点
    while (stack->top!=-1 || p!=NULL) { // 栈不空或者遍历指针不空
        if(p!=NULL){
            push_stack(stack, p);
            p = p->lchild;
        }else{
            if(stack->top+1 > height){
                height = stack->top+1;
            }
            p = pop_stack(stack); //出栈
            std::cout<<p->data<<",";  // 访问
            if(p->rchild!=NULL){
                p = p ->rchild;
            }else{
               p = NULL;
            }
        }
        
    }
    return height;
}

后序遍历


int post_bianli(BiTree T){  //后序遍历
    int height = 0;  // 求树的深度
   
    
    Stack stack = init_Stack();  // 初始化空栈
    TNode* pre , *p;
    p = T; // 遍历指针
    pre = NULL; //上一个访问的结点
    while (stack->top!=-1 || p!=NULL) { // 栈不空或者遍历指针不空
        if(p!=NULL){
            push_stack(stack, p);
            p = p->lchild;
        }else{
            if(stack->top+1 > height){
                height = stack->top+1;
            }
            p = stack->nodes[stack->top];  // 取栈顶元素
            if(p->rchild!=NULL && p->rchild!=pre){
                p = p ->rchild;
            }else{
                p = pop_stack(stack); //出栈
                std::cout<<p->data<<",";  // 出栈访问
                pre = p;  //记录最近访问结点
                p = NULL;
            }
        }
        
    }
    return height;
}

层次遍历


void cengci_bianli(BiTree T){ // 层次遍历
    int weight = 0;
    int height = 0;
    
    Queen q = init_queen(); // 初始化对列
    TNode* p = T;
    in_queen(q, p);
    
    TNode * last = p;  // 记录每层的最后一个结点 当这个节点出队时更新
    
    while (q->front!=q->rear || p!=NULL) { // 队列不空或者遍历指针不空
        p = out_queen(q);
        std::cout<<p->data<<",";

        
        if(p->lchild!=NULL){
            in_queen(q, p->lchild);
            
        }
        if(p->rchild!=NULL){
            in_queen(q, p->rchild);
            
        }
        if(p == last){  // 高度更新
            height ++;
            if ((q->rear-q->front+q->size)%q->size > weight) { // 宽度更新
                weight = (q->rear-q->front+q->size)%q->size;
            }
            last = q->nodes[(q->rear)%q->size];  // 队尾元素是下一层的最后一个节点
        
        }
        p = NULL;
    }
    std::cout<<"树的高度为:"<<height<<"\n";
    std::cout<<"树的宽度为:"<<weight<<"\n";
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树可以用链式存储结构或者数组存储结构来实现。下面是链式存储结构的实现: ```c typedef struct Node { int data; struct Node *leftChild; struct Node *rightChild; } Node; // 前序遍历 void preOrder(Node *root) { if (root != NULL) { printf("%d ", root->data); preOrder(root->leftChild); preOrder(root->rightChild); } } // 中序遍历 void inOrder(Node *root) { if (root != NULL) { inOrder(root->leftChild); printf("%d ", root->data); inOrder(root->rightChild); } } // 后序遍历 void postOrder(Node *root) { if (root != NULL) { postOrder(root->leftChild); postOrder(root->rightChild); printf("%d ", root->data); } } ``` 其中,前序遍历先访问根节点,再访问左子树,最后访问右子树;中序遍历先访问左子树,再访问根节点,最后访问右子树;后序遍历先访问左子树,再访问右子树,最后访问根节点。 如果使用数组存储结构,可以按照如下方式实现: ```c #define MAX_SIZE 100 int tree[MAX_SIZE]; // 前序遍历 void preOrder(int root, int size) { if (root < size) { printf("%d ", tree[root]); preOrder(root * 2 + 1, size); preOrder(root * 2 + 2, size); } } // 中序遍历 void inOrder(int root, int size) { if (root < size) { inOrder(root * 2 + 1, size); printf("%d ", tree[root]); inOrder(root * 2 + 2, size); } } // 后序遍历 void postOrder(int root, int size) { if (root < size) { postOrder(root * 2 + 1, size); postOrder(root * 2 + 2, size); printf("%d ", tree[root]); } } ``` 数组实现中,左子节点的下标为 root * 2 + 1,右子节点的下标为 root * 2 + 2。下标从 0 开始,因此如果树的节点数为 n,数组的大小应该为 2^n - 1。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值