集训第六天
今天学习了树,然后我看了一个约瑟夫问题,其中树包括一般树,二叉树中的完全二叉树,满二叉树等等,当然还有树的实现,今天讲的是用数组实现的二叉树,下午我用了链表实现了一下,它的实现其实并不算难,但是有一点值得注意的就是递归的使用。
递归用起来真的很方便,但是还是有需要注意的,(按照先序遍历的方式)
首先就是要创建一个根结点,然后在去创建他的左子树,然后是右子树,值得关注的是该函数是有返回值的,这样的话可以根据返回的情况来判断左子树和右子树是不是空的;
struct NODE *CreateTree(void)
{
charch;
structNODE *p = NULL;
scanf("%c",&ch);
if(' ' == ch)
{
returnp;
}
else
{
p= (struct NODE *)malloc(sizeof(struct NODE));
p->ch= ch;
p->lchild= CreateTree();
p->rchild= CreateTree();
returnp;
}
}
然后就是对二叉树的遍历,有4中遍历方式,但是经常用到的有三种,分别是先序遍历,中序遍历,后序遍历,先中后指的是对根节点输出的先后顺序,同样用到了递归的方法,拿先序遍历为例:首先就是要判断是否为空,这也是在创建树的时候返回的NULL或者是!NULL,
然后就是输出根节点中存放的数据,然后就是对左子树遍历,然后是右子树,这样就能得到树;
bool traverse(struct NODE *p)
{
if(!p)
returntrue;
visit(p->ch);
traverse(p->lchild);
traverse(p->rchild);
returntrue;
}
void visit(char ch)
{
printf("%c", ch);
}
其次就是求树的深度,还是递归,如果子树不为空,就继续调用depth函数吗,直到子树为空,返回其中最大的,即为树的深度;
int depth(struct NODE *p)
{
intl; //左子树的深度
intr; //右子树的深度
if(p == NULL)
{
return0;
}
if( p->lchild )
{
l= depth(p->lchild);
}
else
{
l= 0;
}
if( p->rchild )
{
r= depth(p->rchild);
}
else
{
r= 0;
}
return(l>r) ? (l+1) : (r+1);
}
对于约瑟夫问题,它就是一个循环单链表吧,其中有一步的操作很重要,就是取余的操作,循环的数要对总数取余,然后就是循环到循环数的前一个数,然后输出那个数,删去该结点,其他就是一些链表的操作:
# include <stdio.h>
# include <stdlib.h>
typedef struct node
{
intdata;
structnode *next;
}node;
node *create(int n)
{
node*p = NULL, *head;
head= (node *)malloc(sizeof(node));
p= head;
node*s;
inti = 1;
if(n)
{
while(i <= n)
{
s= (node *)malloc(sizeof(node));
s->data= i++;
p->next= s;
p= s;
}
s->next= head->next;
}
free(head);
returns->next;
}
int main()
{
intn = 41;
intm = 3;
inti;
node*p = create(n);
node*temp;
m%= n;
while(p != p->next)
{
for(i=1; i<m-1; i++)
{
p= p->next;
}
printf("%d->",p->next->data);
temp= p->next;
p->next= temp->next;
free(temp);
p= p->next;
}
printf("%d\n",p->data);
return0;
}