家谱图-二叉树

用二叉树实现家谱的相关运算 /** * 实验题目 * 用二叉树实现家谱的相关运算 * 实验内容 * 编写程序,采用一棵二叉树表示一个家谱关系。要求程序具有如下功能: * 1、文件操作功能: * 记录输入,记录输出,清除全部文件记录和将家谱记录存盘。 * 2、家谱操作功能: * 用括号表示法和凹入表示法输出家谱二叉树,查找某人的所有儿子,查找 * 某人所有祖先... 阅读详情
// FamilyMap_BTree.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"


#define fileName "familyMap.dat"


//定义节点最大个数
#define MaxNode 20


//节点数据类型
typedef char ElemType;


//二叉树节点类型(节点类型)
typedef struct btnode{
	ElemType data;				//家谱图中人员编号
	btnode * lchild;			//成员的配偶指针
	btnode * rchild;			//成员的子女及子女的兄弟指针
}BtNode;


typedef BtNode *BTree;			//定义BtNode *类型为BTree


//二叉树栈
typedef struct{
	BtNode * stack[MaxNode];	//栈区
	int top;					//栈顶指针
}BTreeStack;

typedef struct{
	BtNode * pNode;
	int height;
}BtNodewithHeight;

//二叉树队列
typedef struct{
	BtNodewithHeight queue[MaxNode];	//队列数据区
	int front;							//队列头指针
	int rear;							//队列尾指针
}BTreeQueue;




//从文件中读取系谱图(以括号表示法储存)
bool ReadfromFile(char *&s){
	FILE *fp = NULL;
	fopen_s(&fp,fileName,"rb");
	int size=0;
	if (fp == NULL)
		return false;
	fseek(fp, 0L, SEEK_END);
	size = ftell(fp);


	s = (char *)malloc(sizeof(size+1));		//在这里分配了内存空间,在外面使用,最后释放


	*(s + size) = '\0';
	fread(s,size,1,fp);
	fclose(fp);
	return true;
}


//从括号表述法创建二叉树(使用栈进行实现)
bool CreateBTreefromBracketNotation(BTree &r, char * btStr){
	BTreeStack bts;
	bts.top = -1;						//初始化栈


	int i = 0, k = 0;					//i用于保存串的偏移量,k用于标记处理栈顶的左指针还是右指针
	char ch;						//ch用于保存括号表示法串的字符
	BtNode * temp = NULL;				//temp用于保存待处理的节点
	while ((ch = *(btStr + i)) != '\0')	//循环扫描串,并将字符存到ch
	{
		switch (ch){
		case '(':					//将子树根节点进栈,准备处理根节点左指针
			bts.stack[++bts.top] = temp;
			k = 1;
			break;
		case ')':					//子树根节点出栈
			bts.top--;
			break;
		case ',':					//准备处理子树根节点右指针
			k = 2;
			break;
		default:					//处理数据节点
			temp = (BtNode *)malloc(sizeof(BtNode));
			temp->data = ch;
			temp->lchild = temp->rchild = NULL;
			switch (k){
			case 0:
				r = temp;
				break;
			case 1:
				bts.stack[bts.top]->lchild = temp;
				break;
			case 2:
				bts.stack[bts.top]->rchild = temp;
				break;
			}
			break;
		}
		i++;
	}
	return true;
}


//寻找某人的所有孩子函数(递归实现)
//@BTree r表示子树的根节点
//@char e表示要寻找的节点编号
//@bool src储存得到该节点的路径(左还是右) true代表左 false代表右 第一次调用时(即根节点时)src为true
bool FindAllSon(BTree r, char e ,bool src){
	if (r == NULL)											//递归出口
		return false;							
	if (r->data == e){										//找到该人
		BtNode * temp=NULL;
		if(src==true){										//表示该节点为家族外来人,孩子直接挂在他的右子树上
			temp=r->rchild;
			if(temp==NULL)
				printf("%c没有孩子\n",e);
			else{
				printf("%c的孩子有:\t",e);
				while(temp!=NULL){
					printf("%c\t",temp->data);
					temp=temp->rchild;
					}
				printf("\n");
				}
		}else{												//表示该节点为家族内部人,孩子挂在他的配偶身上(即左子树的右子树上)
			if(r->lchild==NULL)
				printf("哥们,%c配偶都没有,哪来的孩子啊...\n",e);
			else{
				temp=r->lchild->rchild;
				if(temp==NULL)
					printf("%c还没有孩子\n",e);
				else{
					printf("%c的孩子有:\t",e);
					while(temp!=NULL){
					printf("%c\t",temp->data);
					temp=temp->rchild;
					}
				}
			}
		}
		return true;
	}
	else{
		if (!FindAllSon(r->lchild, e, true))						//寻找左子树
			return FindAllSon(r->rchild,e,false);					//左子树未找到时寻找右子树
		else
			return true;
	}
}


//寻找祖先元素(递归实现)
//@BTree r代表根节点
//@char e代表待寻找的元素编号
//@BTreeStack *bt代表记录节点路径信息的栈
bool FindAllAncestor(BTree r, char e, BTreeStack * bt){
	if (r == NULL)
		return false;												//递归出口,未找到该节点
	int temp = ++bt->top;											//temp储存根节点进栈后的栈顶指针
	bt->stack[temp] = r;											//将根节点进栈
	if (r->data == e){												//递归出口,找到该节点,根据路径判断该节点的祖先元素
		if(bt->top==0)
			printf("%c为该家谱图中的根节点,祖先元素无法找出\n",e);
		else{
			if(bt->stack[bt->top-1]->lchild==bt->stack[bt->top])
				printf("%c是外来人口,根据该家谱图如法得出其祖先元素\n",e);
			else{
				int k=0;											//k记录输出祖先元素的对数
				printf("%c的祖先元素有:\t",e);
				for(int i=0;i<bt->top;i+=2){
					if(bt->stack[i]->lchild==bt->stack[i+1]){
						k++;
						printf("(%c,%c)\t",bt->stack[i]->data,bt->stack[i+1]->data);
					}
				}
				if(k==0)
					printf("null\n");
				else
					printf("\n");
			}
		}
		return true;
	}
	else{
		if (!FindAllAncestor(r->lchild, e, bt)){						//在左子树中找改节点
			bt->top = temp;												//左子树中未找到则退栈
			return FindAllAncestor(r->rchild, e, bt);					//在右子树中寻找该节点
		}
		else
			return true;
	}
}

//以括号表示输出二叉树(递归实现)
void DispbyBracketNotation(BTree r)
{
	if(r!=NULL){
		printf("%c",r->data);
		if(r->lchild!=NULL || r->rchild!=NULL){
			printf("(");
			DispbyBracketNotation(r->lchild);
			if(r->rchild!=NULL)
				printf(",");
			DispbyBracketNotation(r->rchild);
			printf(")");
		}
	}
}

//求二叉树的高度
int HeightofBTree(BTree r,int h)
{
	int lh=h,rh=h;
	if(r->lchild!=NULL)
		lh=HeightofBTree(r->lchild,h+1);
	if(r->rchild!=NULL)
		rh=HeightofBTree(r->rchild,h+1);
	return lh>=rh?lh:rh;
}

//输出星号函数
void printStar(int n)
{
	for(int i=0;i<n;i++)
		printf(" * ");
	printf("\n");
}

//以凹入表示法输出二叉树
void DispbyIndentation(BTree r,BTreeQueue * q)
{
	int h=HeightofBTree(r,1);		//获得树的总高度

	BtNodewithHeight *p=NULL;
	
	q->queue[++q->rear].pNode=r;	//根节点进队
	q->queue[q->rear].height=h;
	
	while(q->front!=q->rear){
		q->front=(q->front+1)%MaxNode;
		p=&(q->queue[q->front]);
		if(p->pNode!=NULL){
			printf("%c:\t",p->pNode->data);
			printStar(p->height);
			q->queue[++q->rear].pNode=p->pNode->lchild;
			q->queue[q->rear].height=p->height-1;
			q->queue[++q->rear].pNode=p->pNode->rchild;
			q->queue[q->rear].height=p->height-1;
		}
		
	}

}

bool FamilyMemberAdd(){
	return false;
}




int _tmain(int argc, _TCHAR* argv[])
{
	char * familyMapStr = "A(B(,D(G(,I(,J)),H)),C(E,F))";	//树的括号表示法字符串

	BTree bt = NULL;										//树的根节点指针

	BTreeStack bs;											//创建二叉树的栈
	bs.top = -1;											//初始化二叉树栈

	BTreeQueue bq;											//创建二叉树队列
	bq.front=bq.rear=-1;										//初始化二叉树队列
	
	char a='F',b='B';

	CreateBTreefromBracketNotation(bt, familyMapStr);		//创建家谱二叉树


	FindAllSon(bt,a,true);									//寻找a变量元素的孩子
	printf("\n");

	if (!FindAllAncestor(bt,b, &bs))						//寻找b变量元素的祖先
		printf("%c的祖先在家谱图中没有得到体现",b);
	printf("\n");

	
	printf("二叉树的括号表示法如下:\n");
	DispbyBracketNotation(bt);
	printf("\n\n");

	printf("二叉树的凹入表示法如下:\n");
	DispbyIndentation(bt,&bq);
	printf("\n");
	//printf("%d\n",HeightofBTree(bt,1));

	system("PAUSE");
	return 0;
}


/***************************
*说明:
*本例要求给出家谱结构图和家谱性别图
*与本家族节点的配偶必须位于左节点,两人结婚所生小孩须挂于外来人的右子树
*新增节点必须给出性别
*根节点如有配偶则配偶必须出现在家谱图中
*祖先元素输出会包括男与女双方,如果显示祖先元素为空,也表示该图中不存在他的祖先元素
***************************/

二叉树实现家谱图---未完成
Java二叉树实战:从基础遍历到高级应用 本文系统讲解了Java中二叉树的核心知识与实战应用。从基础的前序、中序、后序遍历,到层序遍历、完全二叉树判断等进阶操作,均提供了清晰的Java代码实现与解析。文章深入探讨了递归思想在统计、查找、求高度等问题中的应用,并介绍了非递归遍历的实现技巧,最后结合表达式树、决策树等典型场景,帮助开发者将二叉树理论应用于实际项目开发。 阅读详情

相关推荐

高光谱图像数据集

1:Washington DC Mal,Indian Pine等 https://engineering.purdue.edu/~biehl/MultiSpec/hyperspectral.html 2:Indian Pines,Salinas,Pavia Centre and University,Cuprite等 http://www.ehu.eus/ccwintco/index.php?title=Hyperspectral_Remote_Sensing_Scenes 3:hydice的...

haoji007的博客 6841

二叉树家谱系统

二叉树实现家谱系统

m0_64122265的博客 1656

数据结构二叉树家谱

数据结构二叉树家谱:文件操作功能,家谱操作功能

C#写算法之二叉树

在数据结构中,树的定义如下: 树(tree)是n(n>=0)个节点的有限集,当n=0时,称为空树。在任意一个非空树中,有如下特点: 1.有且仅有一个特定的称为根的节点。 2.当n>1时,其余节点可分为m(m>0)个互不相交的有限集,每一个集合本身又是一个树,并称为根的子树。 树有以下概念: 根节点、父节点、兄弟节点、孩子节点。 树的最大层级数,被称为树的高度或深度。 ...

知识无止境 9027

家族族谱系统 二叉树

家族族谱实现,采用二叉树表示一个家谱关系。要求程序具有如下功能: (1) 文件操作功能:记录输入、记录输出,清除全部文件记录和将家谱记录存盘。 (2) 家谱操作功能:用括号表示法输出家谱二叉树,查找某人所有的儿子,查找某人所有的祖先。

算法 二叉树 凹入法家谱

算法与数据结构 实验 用二叉树实现家谱,找父亲的儿子。

用二叉树表示家谱关系并实现各种查找功能

用二叉树表示家谱关系并实现各种查找功能 目的:掌握二叉树遍历算法的应用,熟练使用先序、中序、后序3种递归遍历算法进行二叉树问题的求解。 内容:采用一棵二叉树表示一个家谱关系,要求具有以下功能:①、文件操作功能,即家谱记录的输入、家谱记录的输出、清除全部文件记录和将家谱记录存盘。②、家谱操作功能,即用括号表示法输出家谱二叉树、查找某人的所有儿子、查找某人的所有祖先。 需求分析: 模块1:功能选择 分...

汤姆lazy的优快云博客 2万+

数据结构(二叉树)家谱管理系统

数据结构(二叉树)家谱管理系统,数据结构综合实验题3。

家谱二叉树c语言程序,家谱图-二叉树

// FamilyMap_BTree.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#define fileName "familyMap.dat"//定义节点最大个数#define MaxNode 20//节点数据类型typedef char ElemType;//二叉树节点类型(节点类型)typedef struct btnode{ElemType data...

weixin_39790717的博客 1597

基于JavaScript和C#的FamilyTree家谱电子化项目设计源码

本项目是基于JavaScript和C#的FamilyTree家谱电子化项目设计源码,包含290个文件,其中包括77个DLL文件、30个XML文件、28个JavaScript文件、25个Nupkg文件、24个XDT文件、21个CS文件、12个XML文件、12个PS1文件和9个Config文件。此外,还包括7个CSHTML文件。这个项目旨在实现一个大家族的族谱电子化,通过JavaScript和C#技术栈,提供一个方便、直观的家谱管理系统,帮助用户更好地记录和管理家族成员的信息。

揭秘大型语言模型:从神经元到思维透明的奇妙旅程

这篇博客带你走进大型语言模型的内部世界,从神经元的小任务,到功能向量的团队合作,再到层间的协作和思维的透明化。掌握这些知识,能让你在开发中更高效地优化AI,在研究中更深入地探索模型的奥秘。建议多动手实践,把这些理论变成自己的能力!

数据与算法架构提升之路专栏 1521

数据结构 实验 家族族谱项目

数据结构 实验 家族族谱项目

m0_74394367的博客 4824

MAX30102心率血样模块在STM32F103芯片的程序说明

我希望你已经安装好了Keil MDK5这个软件,也安装了M3内核,可以编译一些STM32F103的一些项目下载程序后步骤: 1-按照下图找到IIC.uvprojx并打开(途中唯一绿色那个图标) 2-编译一次 3-确保0错误,0警告,下图所示 4-点击目标选项,然后找到STM32F103C8,再点debug–CMSIS****(我实际用的JTAG,用不了,选择这个CMSIS****即可)下图所示 5-下图所示,看看你的串口找到了没,找到了就点左下角的OK 6-按图上传到开发板 7-MAX30102接线方法

weixin_51357422的博客 5801

【课设大作业】基于C++的家族族谱项目实现(含代码)

家谱记载了一个家族的世系繁衍及重要人物事迹。使用树型结构对家谱进行管理,实现查看祖先和子孙个人信息,插入家族成员,删除家族成员的功能

java学长的博客 728

05-SA8155 QNX Display框架及代码分析(1)

显示是非常重要的一个模块,人机交互的桥梁。那么SA8155 Hypervisor显示是如何处理的呢。对处理流程非常的好奇O(∩_∩)O哈哈~。TODO。

静虚待令,有物混成 1万+

Plant Simulation新手入门:5步搞定生产线物流仿真(附模型库使用技巧)

本文为Plant Simulation新手提供了从零开始构建生产线物流仿真的五步入门指南。通过理念重塑、流程规划、对象连接、参数设置到数据分析的完整流程,帮助用户快速掌握这一强大仿真工具的核心逻辑。文章特别强调了模型库的高效使用技巧,助力工程师在虚拟环境中精准模拟和优化生产系统,提升规划效率。

efc123456的博客 335

树的遍历查找-家谱树检索

找家谱成员 输入若干行,每一行的第一个输入为家谱中的某成员,该行接着输入的信息为每个孩子姓名。 最后一行的输入为要求查找的二个家谱成员的关系。 要求,根据输入的家谱成员信息,建立二叉树家谱关系图,并输入二位待查成员在家谱中的关系,包括输出他们最近邻的共同祖先以及在家谱中相差的层次数。 输入: Ye Shu Ba Shu Ge Mei1 Ba Self Mei2 Ge Son1 So...

Ulez_柚子的博客 845

【科普知识】什么是驱控一体化伺服电机?

驱控一体化伺服电机以其高度的集成性、兼容性、便捷性以及卓越的性能表现,成为了现代工业自动化领域的一颗璀璨明珠。对于那些追求高效、精准、智能控制的行业用户而言,它无疑是一种理想的选择。

m0_46512607的博客 3151

二叉树入门【C语言实现】

是每个节点最多有两个"孩子"(子节点)的树形数据结构。想象一棵家族树,但每个父母最多只能有两个孩子,这就是二叉树的基本概念。

2401_87882101的博客 680

L298N电机驱动模块的接线使用与代码实现

#include "iostm8s208mb.h" #define u8 uint8_t #define u16 uint16_t #define u32 uint32_t typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; // 关于LED灯的宏定义 #define LED2 PI_ODR_ODR2 //输出量 #define LE

Clichong 13万+

腾讯Android开发面试指南与参考答案

腾讯深圳元宝高级Android开发工程师岗位要求3-5年Android开发经验,熟悉Kotlin和性能优化,具备架构设计能力。岗位职责包括元宝Android客户端研发、稳定性优化及跨团队协作。面试重点考察Kotlin、Jetpack Compose、多线程编程等核心技术,3轮线上面试流程较快。无AI项目经验也可应聘,需突出展示Android架构设计、性能调优等实战能力。建议准备Compose开发、算法等加分项案例。

郑伟强dev的专栏 1133

从混沌到有序:树与二叉树的奇幻之旅

本文介绍了树和二叉树这两种重要的非线性数据结构。树通过节点间的层次关系,能有效模拟文件系统、组织架构等现实场景,其核心概念包括根节点、子节点、深度等。二叉树是树的特殊形式,每个节点最多有两个子节点,具有前序、中序、后序和层序四种遍历方式。文章详细讲解了二叉树的链式存储实现、遍历算法及应用场景,如二叉搜索树、堆等。最后指出任何树都可以转化为二叉树表示,掌握这些数据结构是理解更复杂算法的基础。

2301_78884150的博客 844

【ArcGIS遇上Python】批量提取多波段影像至单个波段

本案例基于ArcGIS python,将landsat影像的7个波段影像数据,批量提取至单个波段。

智慧空间实验室 2074

树、二叉树、堆

一、树 树和图的区别: 上面这个例子中左边的是一棵树,而右边的是一个图。因为左边的没有回路,而右边的存在1->2->5->3->1这样的回路。 1、正是因为树有着“不包含回路”这个特点,所以树就被赋予了很多特性。 2、一棵树中的任意两个结点有且仅有唯一的一条路径连通。 3、一棵树如果有n个结点,那么它一定恰好有n-1条边。 在一棵树中加一条边将会构成一个回路。树这个特殊的数据结构在哪里会用到呢?比如足球世界杯的晋级图,家族的族谱图、公司的组织结构图、书的目录、我们用的操作系统Win

m0_52192682的博客 391

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

上一篇: Binary Tree FamilyMap
下一篇: #ifndef #define #endif
Codelee1995
博客等级 码龄12年 3粉丝 7原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值