您的位置:首页 > 其它

二叉树的链式存储结构 前序 后序 中序 层序遍历操作实现 判断是否完全二叉树

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


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: