赞
踩
以下代码包括:辅助栈(链栈)、辅助队列(顺序存储循环队列)、二叉树的两种先序建立、先序中序后序遍历(递归)、中序遍历非递归方法、层次遍历。注释充分,逻辑清晰,代码可读性强。
#include <stdio.h> #include <malloc.h> #include <stdbool.h> typedef char BiElemType; typedef struct BTNode{ BiElemType data; //数据域 struct BTNode * pLchild; struct BTNode * pRchild; }BTNode, * BiTree; //======================辅助栈的实现======================== typedef struct Node{ BiTree data; struct Node * next; }NODE, * PNODE; typedef struct Stack{ PNODE pTop; //栈顶 PNODE pBottom;//栈底 }STACK, * PSTACK; void init_S(PSTACK pS){//链栈的初始化 PNODE pHead = (PNODE)malloc(sizeof(NODE)); if (pHead == NULL) { printf("内存分配失败!\n"); } pS->pBottom = pHead; //初始栈顶栈底都指向头节点 pS->pTop = pHead; pS->pTop->next = NULL; } void push(PSTACK pS, BiTree val){ //原则:先入栈后变动栈顶指针 PNODE pnew = (PNODE)malloc(sizeof(NODE)); pnew->data = val; pnew->next = pS->pTop; //将新节点接在原栈顶上方 pS->pTop = pnew; //栈顶指针变动至最新位置 return; } void traverse(PSTACK pS){ PNODE p = pS->pTop; //遍历指针获取到栈顶 while(p != pS->pBottom){ printf("%d ", p->data); p = p->next; } printf("\n"); return; } //出栈一次,并将元素输出在val中 bool pop(PSTACK pS, BiTree * p){ //这里用到了二级指针 if(pS->pBottom == pS->pTop){ //栈空报错 return false; } *p = pS->pTop->data; //保存删去的值 PNODE q = pS->pTop; pS->pTop = q->next; //移动栈顶指针 free(q); return true; } bool is_empty(PSTACK S){ if(S->pBottom == S->pTop){ //栈空 return true; }else{ return false; } } //======================辅助队列的实现======================== #define MAX_SIZE 6 //宏定义 数组长度为6,最多能保存5个元素 typedef struct Queue { BiTree * pBase; //数组的首地址 int front; int rear; }QUEUE; void init_Q(QUEUE * pQ){ //初始化一个长度为6的队列 pQ->pBase = (int *)malloc(sizeof(int) * MAX_SIZE); pQ->front = 0; pQ->rear = 0; } //判断队列是否为空(引入一个空单元作为牺牲) bool is_full(QUEUE * pQ){ if((pQ->rear + 1) % MAX_SIZE == pQ->front){ printf("该循环队列已满!\n"); return true; } return false; } bool q_empty(QUEUE * pQ){ if(pQ->rear == pQ->front){ return true; }else{ return false; } } bool en_queue(QUEUE * pQ, PNODE val){ //入队:入队一个元素,队尾向后移动一下 if(is_full(pQ)){ printf("队列已满,无法添加元素!\n"); return false; }else{ pQ->pBase[pQ->rear] = val; pQ->rear = (pQ->rear + 1) % MAX_SIZE; return true; } } bool de_queue(QUEUE * pQ, PNODE * val){ if(pQ->front == pQ->rear){ printf("该队列为空,无法出队!\n"); return false; }else{ *val = pQ->pBase[pQ->front]; pQ->front = (pQ->front + 1) % MAX_SIZE; return true; } } //==============================二叉树功能实现============================================= /* 使用二级指针的原因: 1.若要通过函数B修改函数A中的某个变量a。需要获得变量a的地址,如果 a是普通变量,需要获得一级指针。如果a是指针,需要获得二级指针。 2.root需要指向一个新插入的节点,也就是需要修改root的值。所以 应该传入指向root的地址。 3.如果仅使用一级指针,那么只能改变形参的内存,如,root = malloc(sizeof(struct TreeNode)); 这个root和函数外的实参的内存空间不同,所以修改它并不会对实参的内存造成影响, 所以必须把它做为返回值返回去,否则函数外就没法获得这个变化的值。 */ /* A.先序建立二叉树(无返回值版本) 需要在main函数中定义一个根节点 注意这是个二叉树节点的指针类型;然后将这个参数 传递给一个CreateBTree函数;在该函数中递归创建二叉树 */ void CreateBTree(BiTree * root){ //二级指针(BiTree本身就是指针) char c; scanf("%c", &c); //接受一个字符 if(c == '#'){ //遇到# *root = NULL; //将此节点置为空 }else{ //从函数外部接受root(二级指针的形式)并在函数内部进行修改 (*root) = (BiTree)malloc(sizeof(BTNode)); //创建一个新的节点 (*root)->data = c; CreateBTree(&(*root)->pLchild); //沿左子树继续创建 CreateBTree(&(*root)->pRchild); //沿右子树继续创建 } } /* B.先序建立二叉树(有返回值版) 可以直接在CreatBiTree函数中创建二叉树,并返回二叉树的根指针 */ BiTree CreateBTree2(){ char c; BiTree root = NULL; //在函数内部创建root scanf("%c", &c); //接受一个字符 if(c == '#'){ //遇到# root = NULL; //将此节点置为空 return NULL; //必须return NULL }else{ root = (BiTree)malloc(sizeof(BTNode)); //创建一个新的节点 root->data = c; root->pLchild = CreateBTree2(); //沿左子树继续创建 root->pRchild = CreateBTree2(); //沿右子树继续创建 return root; } } //先序遍历二叉树 void PreOrderTraverse(BiTree root){ if(root != NULL){ printf("%c", root->data); PreOrderTraverse(root->pLchild); PreOrderTraverse(root->pRchild); } } //中序遍历 void InOrderTraverse(BiTree root){ if(root != NULL){ InOrderTraverse(root->pLchild); printf("%c", root->data); InOrderTraverse(root->pRchild); } } //中序遍历非递归方法(借助栈完成) void InOrderTraverse2(BiTree root){ STACK S; //STACK等价于 struct Stack init_S(&S); BiTree t = root; while(!is_empty(&S) || t != NULL){ if(t){ //若当前节点不为空则将其入栈,继续向左子树遍历 push(&S, t); //入栈的是整个树节点,并非字符 t = t->pLchild; }else{ //若左子树为空,出栈并访问,然后访问其右子树 pop(&S, &t); printf("%c", t->data); t = t->pRchild; } } } //后序遍历 void PostOrderTraverse(BiTree root){ if(root != NULL){ PostOrderTraverse(root->pLchild); PostOrderTraverse(root->pRchild); printf("%c", root->data); } } //层次遍历 void LevelOrder(BiTree root){ QUEUE Q; //实例化一个队列 init_Q(&Q); en_queue(&Q, root); //将根节点入队 BiTree val; //保存出队元素 while(!q_empty(&Q)){ de_queue(&Q, &val); printf("%c", val->data); if(val->pLchild != NULL){ en_queue(&Q, val->pLchild); } if(val->pRchild != NULL){ en_queue(&Q, val->pRchild); } } } int main(){ //A.二级指针构造方式 // BiTree root = NULL; // CreateBTree(&root); // PreOrderTraverse(root); //B.一级指针构造方式 BiTree root = CreateBTree2(); printf("先序遍历二叉树\n"); PreOrderTraverse(root); printf("\n"); printf("中序遍历二叉树\n"); InOrderTraverse(root); printf("\n"); printf("后序遍历二叉树\n"); PostOrderTraverse(root); printf("\n"); printf("非递归中序遍历二叉树\n"); InOrderTraverse2(root); printf("\n层次遍历二叉树\n"); LevelOrder(root); return 0; }
程序运行:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。