您的位置:首页 > 理论基础 > 数据结构算法

数据结构与算法--二叉树(二)

2016-04-22 08:24 513 查看
======================================================

二叉链表.c

#define _CRT_SECURE_NO_WARNINGS

#include <stdlib.h>

#include <string.h>

#include <stdio.h>

//1

typedef struct BiTNode

{

int data;

struct BiTNode *lchild, *rchild;

}BiTNode;

typedef struct BiTNode * BiTree;

//2

//第二种表示方法 三叉链表

//三叉链表

typedef struct TriTNode

{

int data;

//左右孩子指针

struct TriTNode *lchild, *rchild;

struct TriTNode *parent;

}TriTNode, *TriTree;

//双亲链表

#define MAX_TREE_SIZE 100

typedef struct BPTNode

{

int data;

int parentPosition; //指向双亲的指针 //数组下标

char LRTag; //左右孩子标志域

}BPTNode;

typedef struct BPTree

{

BPTNode nodes[100]; //因为节点之间是分散的,需要把节点存储到数组中

int num_node; //节点数目

int root; //根结点的位置 //注意此域存储的是父亲节点在数组的下标

}BPTree;

//用这个数据结构能表达出一颗树。。。能,怎么表达?不能why

void main()

{

BPTree myTree; //

myTree.root = 0; //数组的0号位置 是根结点

myTree.nodes[0].data = 'A';

//B

myTree.nodes[1].data = 'B';

myTree.nodes[1].parentPosition = 0;

myTree.nodes[1].LRTag = 1;

//C

myTree.nodes[2].data = 'C';

myTree.nodes[2].parentPosition = 0;

myTree.nodes[2].LRTag = 2;

system("pause");

}

void main11()

{

BiTNode nodeA, nodeB, nodeC, nodeD, nodeE;

nodeA.lchild = NULL;

nodeA.rchild = NULL;

nodeA.data = 0;

memset(&nodeA, 0, sizeof(BiTNode));

memset(&nodeB, 0, sizeof(BiTNode));

memset(&nodeC, 0, sizeof(BiTNode));

memset(&nodeD, 0, sizeof(BiTNode));

memset(&nodeE, 0, sizeof(BiTNode));

nodeA.data = 1;

nodeA.lchild = &nodeB;

nodeA.rchild = &nodeC;

nodeB.lchild = &nodeD;

nodeC.lchild = &nodeE;

printf("hello...\n");

system("pause");

return ;

}

============================================================

树的操作.c

#define _CRT_SECURE_NO_WARNINGS

#include <stdlib.h>

#include <string.h>

#include <stdio.h>

//1

typedef struct BiTNode

{

int data;

struct BiTNode *lchild, *rchild;

}BiTNode;

typedef struct BiTNode * BiTree;

//先序遍历

void preOrder(BiTNode *T)

{

if (T == NULL)

{

return ;

}

printf("%d ", T->data); //

if (T->lchild != NULL)

{

preOrder(T->lchild);

}

if (T->rchild != NULL)

{

preOrder(T->rchild);

}

}

void InOrder(BiTNode *T)

{

if (T == NULL)

{

return ;

}

if (T->lchild != NULL)

{

InOrder(T->lchild);

}

printf("%d ", T->data); //

if (T->rchild != NULL)

{

InOrder(T->rchild);

}

}

void PostOrder(BiTNode *T)

{

if (T == NULL)

{

return ;

}

if (T->lchild != NULL)

{

PostOrder(T->lchild);

}

if (T->rchild != NULL)

{

PostOrder(T->rchild);

}

printf("%d ", T->data); //

}

/*

1

2 3

4 5

*/

//求树的叶子结点的个数

int sum = 0;

void coutLeafNum(BiTNode *T)

{

if (T == NULL)

{

return ;

}

if (T->lchild == NULL && T->rchild ==NULL)

{

sum ++;

}

coutLeafNum(T->lchild); //求左子树的叶子结点个数

coutLeafNum(T->rchild); //求右子树 叶子结点个数

}

//1 递归函数遇上全局变量 ===>函数参数

//2 //遍历的本质 强化

//访问树的路径是相同的,是不过是计算叶子结点的时机不同....

void coutLeafNum2(BiTNode *T, int *sum)

{

if (T == NULL)

{

return ;

}

if (T->lchild == NULL && T->rchild ==NULL)

{

//*sum++;

//*sum = *sum +1;

(*sum )++ ; //++后置 ++ 先*p 然后sum++

//1 p++

//1 是让实参++ 而不是让地址++

}

coutLeafNum2(T->lchild, sum); //求左子树的叶子结点个数

coutLeafNum2(T->rchild, sum); //求右子树 叶子结点个数

}

void coutLeafNum3(BiTNode *T, int *sum)

{

if (T == NULL)

{

return ;

}

coutLeafNum3(T->lchild, sum); //求左子树的叶子结点个数

coutLeafNum3(T->rchild, sum); //求右子树 叶子结点个数

if (T->lchild == NULL && T->rchild ==NULL)

{

(*sum )++ ; //计算叶子结点

}

}

//求树的高度

int Depth(BiTNode *T)

{

int depthval = 0;

int depthLeft = 0, depthRight = 0;

if (T == NULL)

{

return 0;

}

depthLeft = Depth(T->lchild); //求左子树的高度

depthRight = Depth(T->rchild); //求右子树的高度

//1 + 谁大要谁

depthval = 1 + ( (depthLeft>depthRight) ? depthLeft :depthRight );

return depthval;

}

//copy二叉树

BiTNode* CopyTree(BiTNode *T)

{

BiTNode *newlptr = NULL;

BiTNode *newRptr = NULL;

BiTNode *newNode = NULL;

if (T == NULL)

{

return NULL;

}

newlptr = CopyTree(T->lchild);

newRptr = CopyTree(T->rchild);

//new结点

newNode = (BiTNode *)malloc(sizeof(BiTNode)) ; //

if (newNode == NULL)

{

return NULL;

}

newNode->data = T->data; //从旧树中copy数据

newNode->lchild = newlptr; //新的左子树

newNode->rchild = newRptr; //新的右子树

return newNode;

}

void main()

{

BiTNode nodeA, nodeB, nodeC, nodeD, nodeE;

nodeA.lchild = NULL;

nodeA.rchild = NULL;

nodeA.data = 0;

memset(&nodeA, 0, sizeof(BiTNode));

memset(&nodeB, 0, sizeof(BiTNode));

memset(&nodeC, 0, sizeof(BiTNode));

memset(&nodeD, 0, sizeof(BiTNode));

memset(&nodeE, 0, sizeof(BiTNode));

nodeA.data = 1;

nodeB.data = 2;

nodeC.data = 3;

nodeD.data = 4;

nodeE.data = 5;

nodeA.lchild = &nodeB;

nodeA.rchild = &nodeC;

nodeB.lchild = &nodeD;

nodeC.lchild = &nodeE;

//拷贝二叉树

{

BiTNode *newTree = NULL;

newTree = CopyTree(&nodeA);

printf("\n中序遍历新树:");

InOrder(newTree);

}

{

//求树的高度

int depth = Depth(&nodeA);

printf("depth:%d \n", depth);

}

//计算树的叶子结点

{

int mysum = 0;

coutLeafNum(&nodeA);

printf("sum:%d \n", sum);

coutLeafNum2(&nodeA, &mysum);

printf("mysum:%d \n", mysum);

mysum = 0;

coutLeafNum3(&nodeA, &mysum);

printf("mysum:%d \n", mysum);

}

//printf("\n先序遍历树: ");

//preOrder(&nodeA);

printf("\n中序遍历树: ");

InOrder(&nodeA);

//printf("\n后序遍历树: ");

//PostOrder(&nodeA);

system("pause");

}

=========================================================

中序递归.c

#include <iostream>

using namespace std;

#include "stack"

//1

typedef struct BiTNode

{

int data;

struct BiTNode *lchild, *rchild;

}BiTNode;

typedef struct BiTNode * BiTree;

//递归 中序遍历

void InOrder(BiTNode *T)

{

if (T == NULL)

{

return ;

}

if (T->lchild != NULL)

{

InOrder(T->lchild);

}

printf("%d ", T->data); //

if (T->rchild != NULL)

{

InOrder(T->rchild);

}

}

BiTNode * GoFarLeft(BiTNode *T, stack<BiTNode *> &s)

{

if (T ==NULL)

{

return NULL;

}

while (T->lchild != NULL) //一直往左走 ,找到中序遍历的起点

{

s.push(T);

T = T->lchild; //让指针下移

}

return T; //

}

void MyInOrder(BiTNode *T)

{

stack<BiTNode *> s; //

BiTNode *t = GoFarLeft(T, s); //一直往左走 找到中序遍历的起点

while (t != NULL)

{

printf("%d ", t->data);

//若结点 有右子树,重复步骤1

if (t->rchild != NULL)

{

t = GoFarLeft(t->rchild, s);

}

//若结点 没有右子树 看栈是否为空

else if ( !s.empty() )

{

t = s.top(); //把栈顶弹出

s.pop();

}

else

{

t = NULL;

}

}

}

void main()

{

BiTNode nodeA, nodeB, nodeC, nodeD, nodeE;

nodeA.lchild = NULL;

nodeA.rchild = NULL;

nodeA.data = 0;

memset(&nodeA, 0, sizeof(BiTNode));

memset(&nodeB, 0, sizeof(BiTNode));

memset(&nodeC, 0, sizeof(BiTNode));

memset(&nodeD, 0, sizeof(BiTNode));

memset(&nodeE, 0, sizeof(BiTNode));

nodeA.data = 1;

nodeB.data = 2;

nodeC.data = 3;

nodeD.data = 4;

nodeE.data = 5;

nodeA.lchild = &nodeB;

nodeA.rchild = &nodeC;

nodeB.lchild = &nodeD;

nodeC.lchild = &nodeE;

printf("\n中序遍历递归算法");

InOrder(&nodeA);

printf("\n中序遍历非递归算法");

MyInOrder(&nodeA);

cout<<"hello..."<<endl;

system("pause");

return ;

}

====================================================

树的线索化.c

#define _CRT_SECURE_NO_WARNINGS

#include "string.h"

#include "stdio.h"

#include "stdlib.h"

/* Link==0表示指向左右孩子指针, */

/* Thread==1表示指向前驱或后继的线索 */

#define Thread 1

#define Link 0

typedef struct BiThrNode /* 二叉线索存储结点结构 */

{

char data;
/* 结点数据 */

struct BiThrNode *lchild, *rchild;
/* 左右孩子指针 */

int LTag;

int RTag;
/* 左右标志 */

} BiThrNode, *BiThrTree;

char Nil='#'; /* 字符型以空格符为空 */

/* 按前序输入二叉线索树中结点的值,构造二叉线索树T */

BiThrNode* CreateBiThrTree()

{

BiThrNode *tmp = NULL;

char ch;

scanf("%c",&ch);

if (ch == '#')

{

return NULL;

}

else

{

tmp = (BiThrNode *)malloc(sizeof(BiThrNode));

if (tmp == NULL)

{

return NULL;

}

memset(tmp, 0, sizeof(BiThrNode));

tmp->data = ch;

tmp->lchild = CreateBiThrTree(); /* 递归构造左子树 */

tmp->rchild = CreateBiThrTree();

}

return tmp;

}

BiThrNode *pre; /* 全局变量,始终指向刚刚访问过的结点 */

/* 中序遍历进行中序线索化 */

void InThreading(BiThrNode *p)

{

if(p)

{

InThreading(p->lchild); // 递归左子树线索化

if(p->lchild == NULL)
// 没有左孩子

{

p->LTag = Thread;
p->lchild = pre; //前驱线索 左孩子指针指向前驱

}

if(pre->rchild == NULL) // 前驱没有右孩子

{

pre->RTag = Thread; pre->rchild = p;
// 后继线索 前驱右孩子指针指向后继(当前结点p)

}

pre = p;
// 保持pre指向p的前驱

InThreading(p->rchild); // 递归右子树线索化

}

}

/* 中序遍历二叉树T,并将其中序线索化,Thrt指向头结点 */

BiThrNode* InOrderThreading(BiThrTree T)

{

BiThrNode *Thrt = NULL;

Thrt = (BiThrNode *)malloc(sizeof(BiThrNode)); //建头结点

if (Thrt == NULL)

{

return NULL;

}

memset(Thrt, 0, sizeof(BiThrNode));

Thrt->LTag = Link; //左孩子为孩子指针

Thrt->RTag = Thread; //右孩子为线索化的指针

Thrt->rchild = Thrt; // 右指针回指 */ //步骤2和4

if(T == NULL) // 若二叉树空,则左指针回指

{

Thrt->lchild = Thrt; //步骤1和3

}

else

{

Thrt->lchild = T;
//步骤1

pre = Thrt ;

InThreading(T);
// 中序遍历进行中序线索化

pre->rchild = Thrt;
//步骤4

pre->RTag = Thread;
// 最后一个结点线索化

Thrt->rchild = pre;
//步骤2

}

return Thrt;

}

/* 中序遍历二叉线索树T(头结点)的非递归算法 */

int InOrderTraverse_Thr(BiThrNode* T)

{

BiThrNode* p;

p = T->lchild; /* p指向根结点 */

while (p != T)

{

/* 空树或遍历结束时,p==T */

while (p->LTag == Link)

p = p->lchild;

printf("%c ", p->data);

//如果中序遍历的最后一个结点的 右孩子 == T 说明到最后一个结点 ,遍历结束..

while (p->RTag==Thread && p->rchild!=T)

{

p = p->rchild;

printf("%c ", p->data);

}

p = p->rchild;

}

return 0;

}

/* 中序遍历二叉线索树T(头结点)的非递归算法 */

int InOrderTraverse_Thr2(BiThrNode* T)

{

BiThrNode* p;

p = T->rchild; /* p指向根结点 */

while (p != T)

{

/* 空树或遍历结束时,p==T */

while (p->RTag == Link)

p = p->rchild;

printf("%c ", p->data);

//如果中序遍历的最后一个结点的 右孩子 == T 说明到最后一个结点 ,遍历结束..

while (p->LTag==Thread && p->lchild!=T)

{

p = p->lchild;

printf("%c ", p->data);

}

p = p->lchild;

}

return 0;

}

int main()

{

BiThrTree T, H;

printf("请按前序输入二叉树(如:'ABDH##I##EJ###CF##G##')\n");

T = CreateBiThrTree(); // 按前序产生二叉树

H = InOrderThreading(T); // 中序遍历,并中序线索化二叉树

printf("中序遍历(输出)二叉线索树:\n");

InOrderTraverse_Thr(H); // 中序遍历(输出)二叉线索树

printf("\n逆序访问:");

InOrderTraverse_Thr2(H);

printf("\n");

system("pause");

return 0;

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