求节点算法
① 完全二叉树叶子节点的算法
设:度为i的结点数为ni,由二叉树的性质可知:
n0 = n2 + 1……………………①式
n = n0 + n1 + n2……………②式
由①式可得 n2 = n0 - 1,带入②式得:
n0 = (n + 1 - n1)/ 2
由完全二叉树性质可知:
如图,当n为偶数时,n1 = 1, n0 = n / 2
将两式合并,写作:n0 = ⌊(n+1)/2⌋(向下取整符号不能丢)
(1)求节点算法扩展阅读:
完全二叉树的特点:
1.叶子结点只可能在层次最大的两层上出现。
2.对任一结点,若其由分支下的子孙的最大层次为l,则其左分支下的子孙的最大层次必为l或l+1。
完全二叉树的性质:
1.具有n个结点的完全二叉树的深度为⌊log₂n⌋+1。
2.如果对一棵有n个结点的完全二叉树的结点按层序编号,则对任一结点i,有:
(1)如果i=1,则结点i是二叉树的根节点,无双亲;如果i>1,则其双亲是结点⌊i/2⌋。
(2)如果2i>n,则结点i无左孩子;否则其左孩子是结点2i。
(3)如果2i+1>n,则结点i无右孩子;否则其右孩子是结点2i+1。
② 关节点的求解算法
利用深度优先搜索便可以求的图的关节点,本由此可判别图是否重连通。
从任一点出发深度优先遍历得到优先生成树,对于树中任一顶点V而言,其孩子节点为邻接点。由深度优先生成树可得出两类关节点的特性:
(1)若生成树的根有两棵或两棵以上的子树,则此根顶点必为关节点。因为图中不存在连接不同子树顶点的边,若删除此节点,则树便成为森林。
(2)若生成树中某个非叶子节点V,其某棵子树与V的祖先节点无连接,则V为关节点。因为删去v,则其子树和图的其它部分被分割开来 low[v] 设对连通图G=(V,E)进行先深搜索的先深编号为dnf[v],产生的先深生成树为S=(V,T),B试回退边之集。对每个顶点v,low[v]定义如下
low[v]=Min{dfn[v],Min{low[w]|w是v的一个子女},Min{dfn[x]|(v,x)是一条回边}}//dfn数组记录顶点的深度优先数
算法: 求无向图的双连通分量
输入:连通的无向图G=( V, E )。L[v]表示关于v的邻接表
输出:G的所有双连通分量,每个连通分量由一序列的边组成。 1.计算先深编号:对图进行先深搜索,计算每个结点v的先深编号dnf[v],形成先深生成树S=(V,T)。
2.计算low[v]:在先深生成树上按后根顺序进行计算每个顶点v的 low[v], low[v]取下述三个结点中的最小者:
(1) dfn[v];
(2) dfn[w],凡是有回退边(v,w)的任何结点w;
(3) low[y],对v的任何儿子y。
3.求关节点:
(1)树根是关节点,当且仅当它有两个或两个以上的儿子(第一类关节点);
(2)非树根结点v是关节点当且仅当v有某个儿子y,使low[y]≥dnf[v](第二类关节点)。
求双连通分量的算法――同先深搜索算法(略)
③ 完全二叉树叶子节点的算法
设二叉树的叶子节点数为n0,度数为2的节点数为n2,设n1为二叉树中度为1的节点数
因为二叉树中所有节点的度都钓鱼或者等于2,所以二叉树节点总数n=n0+n1+n2
再看二叉树的分支数,除了根节点外,其余节点都有一个分支进入,设B为分支总数,则n=B+1
由于这些分支都是有度为1或者2 的节点射出的,所以B=n1+n2;于是有n=n1+2*n2+1
综合n=n0+n1+n2和n=n1+2*n2+1两式即可得到n0=n2+1
完全二叉树是特殊的二叉树,对于n0=n2+1当然成立
④ 求C语言统计一棵二叉树节点总数的算法(只要函数)
用递归啊,除了叶子节点以外,每个节点都有左子树和右子树,只要判断子节点不为空就用递归调用函数统一子树的节点数,例如
f(t)=f(l)+f(r)+1;
节点总数等于左子树的节点数+右子树的节点数+1
⑤ 求叶子节点的算法
你的k要定义到int leaf_a(BTree root)函数外面去,定义成全局变量,每次递归的k是形参,每次调用都是不一样的
我试过是对的
⑥ 节点的算法
#include <stdio.h>
# include<stdlib.h>
#include <malloc.h>
typedef int datatype;
int p=0,d=0;
typedef struct node
{
datatype data;
struct node *lchild;
struct node *rchild;
}BINTNODE;
typedef BINTNODE *BINTREE;
void createbintree(BINTREE *t)
{
int a;
scanf("%d",&a);
if(a==0)
*t=NULL;
else
{
*t=(BINTNODE *)malloc(sizeof(BINTNODE));
(*t)->data=a;
createbintree(&(*t)->lchild);
createbintree(&(*t)->rchild);
}
}
void preorder(BINTREE T)
{
if(T)
{
printf("%d ",T->data);
d++;
preorder(T->lchild);
preorder(T->rchild);
if(((T->lchild)==NULL)&&((T->rchild)==NULL))
p++;
}
}
main()
{
BINTREE t=NULL;
printf("\nplease input nodes of BINTREE:");
createbintree(&t);
printf("the preorder is:");
preorder(t);
printf("\n叶子节点数:%d",p);
printf("\n总节点数:%d",d);
}
是这样的吗?
⑦ 关于树的结点算法,请大家帮帮忙,过程详细点,谢谢!!!
#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#define Max 20 //结点的最大个数
typedef struct node{
char data;
struct node *lchild,*rchild;
}BinTNode; //自定义二叉树的结点类型
typedef BinTNode *BinTree; //定义二叉树的指针
int NodeNum,leaf; //NodeNum为结点数,leaf为叶子数
//==========基于先序遍历算法创建二叉树==============
//=====要求输入先序序列,其中加入虚结点"#"以示空指针的位置==========
BinTree CreatBinTree(void)
{
BinTree T;
char ch;
if((ch=getchar())==' ')
return(NULL); //读入#,返回空指针
else{
T=(BinTNode *)malloc(sizeof(BinTNode));//生成结点
T->data=ch;
T->lchild=CreatBinTree(); //构造左子树
T->rchild=CreatBinTree(); //构造右子树
return(T);
}
}
//========NLR 先序遍历=============
void Preorder(BinTree T)
{
if(T) {
printf("%c",T->data); //访问结点
Preorder(T->lchild); //先序遍历左子树
Preorder(T->rchild); //先序遍历右子树
}
}
//========LNR 中序遍历===============
void Inorder(BinTree T)
{
if(T) {
Inorder(T->lchild); //中序遍历左子树
printf("%c",T->data); //访问结点
Inorder(T->rchild); //中序遍历右子树
}
}
//==========LRN 后序遍历============
void Postorder(BinTree T)
{
if(T) {
Postorder(T->lchild); //后序遍历左子树
Postorder(T->rchild); //后序遍历右子树
printf("%c",T->data); //访问结点
}
}
//=====采用后序遍历求二叉树的深度、结点数及叶子数的递归算法========
int TreeDepth(BinTree T)
{
int hl,hr,max;
if(T){
hl=TreeDepth(T->lchild); //求左深度
hr=TreeDepth(T->rchild); //求右深度
max=hl>hr? hl:hr; //取左右深度的最大值
NodeNum=NodeNum+1; //求结点数
if(hl==0&&hr==0) leaf=leaf+1; //若左右深度为0,即为叶子。
return(max+1);
}
else return(0);
}
//====利用"先进先出"(FIFO)队列,按层次遍历二叉树==========
void Levelorder(BinTree T)
{
int front=0,rear=1;
BinTNode *cq[Max],*p; //定义结点的指针数组cq
cq[1]=T; //根入队
while(front!=rear)
{
front=(front+1)%NodeNum;
p=cq[front]; //出队
printf("%c",p->data); //出队,输出结点的值
if(p->lchild!=NULL){
rear=(rear+1)%NodeNum;
cq[rear]=p->lchild; //左子树入队
}
if(p->rchild!=NULL){
rear=(rear+1)%NodeNum;
cq[rear]=p->rchild; //右子树入队
}
}
}
//==========主函数=================
void main()
{
BinTree root;
int i,depth;
printf("NodeNum:%d\n",NodeNum);
printf("Creat Bin_Tree; Input preorder:"); //输入完全二叉树的先序序列,
// 用#代表虚结点,如ABD###CE##F##
root=CreatBinTree(); //创建二叉树,返回根结点
do { //从菜单中选择遍历方式,输入序号。
printf("\t********** select ************\n");
printf("\t1: Preorder Traversal\n");
printf("\t2: Iorder Traversal\n");
printf("\t3: Postorder traversal\n");
printf("\t4: PostTreeDepth,Node number,Leaf number\n");
printf("\t5: Level Depth\n"); //先判断节点数是否已有。不用再先选择4,求出该树的结点数。
printf("\t0: Exit\n");
printf("\t*******************************\n");
scanf("%d",&i); //输入菜单序号(0-5)
switch (i){
case 1: printf("Print Bin_tree Preorder: ");
Preorder(root); //先序遍历
break;
case 2: printf("Print Bin_Tree Inorder: ");
Inorder(root); //中序遍历
break;
case 3: printf("Print Bin_Tree Postorder: ");
Postorder(root); //后序遍历
break;
case 4: depth=TreeDepth(root); //求树的深度及叶子数
printf("BinTree Depth=%d BinTree Node number=%d",depth,NodeNum);
printf(" BinTree Leaf number=%d",leaf);
break;
case 5:
if(!NodeNum)
TreeDepth(root);
printf("LevePrint Bin_Tree: ");
Levelorder(root); //按层次遍历
break;
default: exit(1);
}
printf("\n");
} while(i!=0);
}
⑧ 求一个计算循环链表节点数目的算法
int number_L(linklist L)
{
int m=1;/*至少一个节点*/
linklist p=L->next;
while(&p!=&L)/*当p和L不是同一个节点*/
{
m++;
p=p->next;
}
return m;
}
若循环链表允许为空表,则加上
if(L==NULL) return 0;
即可
⑨ 求统计二叉树叶子结点数的递归算法
···cpp
由于不知道你的存储方式,假设你是指针存,用孩子兄弟表示法。
(伪)代码:
structnode{
data{
...
}val;
node*fchild,*brother;
}
voidgetnum(nodex){
if(x.fchild==nu)ans++;
else{
getnum(*x.fchild);
getnum(*x.brother);
}
}
就这样
⑩ 写出中序线索二叉树求第n个节点的算法。
在后序序列中,若结点p有右子女,则右子女是其前驱,若无右子女而有左子女,则左子女是其前驱。若结点p左右子女均无,设其中序左线索指向某祖先结点f(p是f右子树中按中序遍历的第一个结点),若f有左子女,则其左子女是结点p在后序下的前驱;若f无左子女,则顺其前驱找双亲的双亲,一直继续到双亲有左子女(这时左子女是p的前驱)。还有一种情况,若p是中序遍历的第一个结点,结点p在中序和后序下均无前驱。
BiThrTree InPostPre (BiThrTree t,p)
//在中序线索二叉树t中,求指定结点p在后序下的前驱结点q
{BiThrTree q;
if (p->rtag==0) q=p->rchild; //若p有右子女,则右子女是其后序前驱
else if (p->ltag==0) q=p->lchild; //若p无右子女而有左子女,左子女是其后序前驱。
else if(p->lchild==null) q=null;//p是中序序列第一结点,无后序前驱
else //顺左线索向上找p的祖先,若存在,再找祖先的左子女
{while(p->ltag==1 && p->lchild!=null) p=p->lchild;
if(p->ltag==0) q=p->lchild; //p结点的祖先的左子女是其后序前驱
else q=null; //仅右单枝树(p是叶子),已上到根结点,p结点无后序前驱
}
return(q); }//结束InPostPre