二叉树的链式存储结构 前序 后序 中序 层序遍历操作实现 判断是否完全二叉树
2016-03-13 15:22
881 查看
#include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 #define YES 1 #define NO 0 typedef int Status; typedef char ElemType; typedef struct BiTreeNode{ ElemType data; struct BiTreeNode *lchild, *rchild; }BiTreeNode, *BiTree; typedef struct QueueNode{ BiTreeNode* binary_tree_node; //存放的"数据"是二叉树的节点的指针 struct QueueNode* next; }QueueNode, *QueueNodePtr; typedef struct LinkQueue{ QueueNodePtr front; QueueNodePtr rear; }LinkQueue, *Queue; //创建头结点,初始化 Status InitQueue(Queue q){ //注意这里的参数不是Queue *q,因为不是要为q分配空间 //而是为了q中的front和rear q->front = (QueueNode*)malloc(sizeof(struct QueueNode)); if( !q->front ) return ERROR; q->rear = q->front; q->front->next = NULL; return OK; } //入队 Status EnterQueue(Queue q, BiTreeNode* binaryTreeNode){ QueueNode* new = (QueueNode*)malloc(sizeof(struct QueueNode)); if( !new ) return ERROR; new->binary_tree_node = binaryTreeNode; new->next = q->rear->next; q->rear->next = new; q->rear = new; return OK; } //出队 Status DeleteQueue(Queue q, BiTreeNode** binaryTreeNode){ if( q->front == q->rear ){ printf("Queue Empty!\n"); return ERROR; } QueueNodePtr t; t = q->front->next; *binaryTreeNode = t->binary_tree_node; q->front->next = t->next; free(t); if( t == q->rear ) q->rear = q->front; return OK; } Status IsQueueEmpty(Queue q){ return q->front == q->rear ? OK : ERROR; } //test Queue //int main(){ /* 测试 1 * 如何为指针分配空间,都是4? * 下面的测试中出现了结构对齐的问题。 printf("%d\n",sizeof(ElemType)); printf("%d\n",sizeof(struct QueueNode*)); printf("%d\n",sizeof(QueueNode)); printf("%d\n",sizeof(QueueNodePtr)); printf("%d\n",sizeof(LinkQueue)); printf("%d\n",sizeof(Queue)); int *p; printf("%d\n",sizeof(p)); */ /* 测试 2 √ * 原来没有写下面这个函数,导致出错: 使用指针之前请保证它有合法值。 main里的三个指针都没有合法值。(from CSDN) ———————————————————————————————————————————————————————————— Status InitBinaryTreeNode(BiTree *T){ *T = (BiTreeNode*)malloc(sizeof(struct BiTreeNode)); if( !*T ) return ERROR; return OK; } ———————————————————————————————————————————————————————————— LinkQueue* q; InitQueue(q); BiTree p; InitBinaryTreeNode(&p); p->data = 'a'; printf("%c ",p->data); BiTree t; InitBinaryTreeNode(&t); t->data = 'c'; printf("%c ",t->data); */ /* 测试 3 LinkQueue* q; InitQueue(q); BiTreeNode *p,*r; InitBinaryTreeNode(&p); InitBinaryTreeNode(&r); p->data = 'a'; printf("%c \n",p->data); EnterQueue(q,p); DeleteQueue(q,&r); printf("%c \n",r->data); // return OK; } //test Queue end */ //初始化二叉树,在要创建二叉树之前调用 Status InitBiTree(BiTree *T){ *T = NULL; return OK; } //初始化二叉树节点。单个节点使用的时候调用此函数,不然指针会成为野指针 Status InitBinaryTreeNode(BiTree *T){ *T = (BiTreeNode*)malloc(sizeof(struct BiTreeNode)); if( !*T ) return ERROR; return OK; } //使用前序遍历的结构进行二叉树的创建 Status CreateBiTree_PreOrder(BiTree* T){ ElemType c; scanf("%c", &c); if( ' ' == c ){ *T = NULL; } else{ *T = (BiTree)malloc(sizeof(struct BiTreeNode)); if( !*T ) return ERROR; (*T)->data = c; CreateBiTree_PreOrder(&(*T)->lchild); CreateBiTree_PreOrder(&(*T)->rchild); } return OK; } void visit(ElemType c,int level){ printf(" %c level is:%d\n", c, level); } void visit_2(ElemType c){ printf("%c ", c); } //递归的前序遍历二叉树 Status PreOrderTraverse(BiTree T,int level){ if( T ){ visit(T->data,level); PreOrderTraverse(T->lchild,level + 1); PreOrderTraverse(T->rchild,level + 1); } return OK; } //递归的中序遍历二叉树 Status InOrderTraverse(BiTree T,int level){ if( T ){ InOrderTraverse(T->lchild,level + 1); visit(T->data,level); InOrderTraverse(T->rchild,level + 1); } return OK; } //递归的后序遍历二叉树 Status PostOrderTraverse(BiTree T,int level){ if( T ){ PostOrderTraverse(T->lchild,level + 1); PostOrderTraverse(T->rchild,level + 1); visit(T->data,level); } return OK; } //层序遍历二叉树<<非递归>> //要进行层序遍历需要借助于队列的辅助:先将二叉树的根入队列,然后将其 //出队列,visit。如果该根有左孩子,则入队;如果该根有右孩子,则入队。 //然后出队,对该出队的节点进行以上的相同的访问。直到对空 Status LevelOrderTraverse(BiTree T){ LinkQueue *q = (LinkQueue*)malloc(sizeof(LinkQueue)); /*有几次代码出错都是 因为这个,指针q没有 指向。 */ InitQueue(q); BiTreeNode* nodePtr; InitBinaryTreeNode(&nodePtr); EnterQueue(q,T); while( !IsQueueEmpty(q) ){ DeleteQueue(q, &nodePtr); visit_2(nodePtr->data); if( nodePtr->lchild != NULL ){ EnterQueue(q,nodePtr->lchild); } if( nodePtr->rchild != NULL ){ EnterQueue(q,nodePtr->rchild); } } return OK; } //判断二叉树是否为空 Status IsTreeEmpty(BiTree T){ return T == NULL ? OK : ERROR; } //计算二叉树的深度 int BiTreeDepth(BiTree T){ int i = 0,j = 0; if( !T ) return 0; if( T->lchild ) i = BiTreeDepth(T->lchild); else i = 0; if( T->rchild ) j = BiTreeDepth(T->rchild); else j = 0; return i>j ? i+1 : j+1; } /* 判断一棵二叉树是否是完全二叉树: * 思路: 借助于队列,先将root入队,当队列不为空的时候,出队一个元素。如果节点不为空, * 则将该节点的左孩子和右孩子入队;如果节点为空,则查找后序出队的元素中是否全 * 是NULL,否则就不是完全二叉树 * */ Status IsCompleteBinaryTree(BiTree T){ Queue q = (Queue)malloc(sizeof(struct QueueNode)); if( !q ) return ERROR; InitQueue(q); BiTree node; InitBinaryTreeNode(&node); EnterQueue(q, T); while( IsQueueEmpty(q) != OK ){ DeleteQueue(q, &node); if( node != NULL ){ EnterQueue(q, node->lchild); EnterQueue(q, node->rchild); } else{ while( IsQueueEmpty(q) != OK ){ DeleteQueue(q, &node); if( node != NULL ) return NO; } } } return YES; } int main(){ int level = 1; BiTree BT; InitBiTree(&BT); if(IsTreeEmpty(BT)) printf("Binary is Empty!\n"); else printf("Exist Element in Tree\n"); printf("Create Binary Tree by PreOrder: "); CreateBiTree_PreOrder(&BT); printf("PreOrder Traverse: \n"); PreOrderTraverse(BT,level); printf("InOrder Traverse: \n"); InOrderTraverse(BT,level); printf("PostOrder Traverse: \n"); PostOrderTraverse(BT,level); printf("LevelOrder Traverse: \n"); LevelOrderTraverse(BT); printf("\nthe Depth of Binary is %d\n",BiTreeDepth(BT)); if(IsCompleteBinaryTree(BT) == YES ) printf("Complete Binary Tree!\n"); else printf("no-Complete Binary Tree!\n"); return 0; }
相关文章推荐
- linux搭建php5 nginx
- Android如何运行真机在eclipse上调试应用?
- HDU.1017A Mathematical Curiosity【遍历求解】
- 构建之法阅读笔记01
- 面向对象编程(一)
- Linux笔记(31)——网络测试命令
- 进程上下文、中断上下文及原子上下文
- openwrt 如何利用dmesage 查看flash,ram等信息
- VTK 7 的chm帮助文件编译过程记录
- 简单二分查找和递归的思想
- Quartz入门指南
- 《读书笔记》程序员的自我修养之线程安全问题
- Linux下软连接的概念
- c++上机作业1
- 【Leetcode】之Find Minimum in Rotated Sorted Array
- 通过VPS SSH隧道使用本地msf
- 我的偶像宋小宝
- C#中接口和抽象类
- Scala学习笔记--第4章 Scala数组
- 第三周项目-换分币