2011年内蒙古自治区数据基础理论大纲

更新时间:2023-05-18 21:38:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

2011年内蒙古自治区数据基础理论大纲

1、给出折半查找的递归算法,并给出算法时间复杂度性分析。

2、约瑟夫环问题(Josephus问题)是指编号为1、2、 ,n的n(n>0)个人按顺时针方向围坐成一圈,现从第s个人开始按顺时针方向报数,数到第m个人出列,然后从出列的下一个人重新开始报数,数到第m的人又出列, ,如此重复直到所有的人全部出列为止。现要求采用循环链表结构设计一个算法,模拟此过程。

#include<stdlib.h>

typedef int datatype;

typedef struct node

{datatype data;

struct node *next;

}listnode;

typedef listnode *linklist;

void jose(linklist head,int s,int m)

{linklist k1,pre,p;

int count=1;

pre=NULL;

k1=head; /*k1为报数的起点*/

while (count!=s) /*找初始报数起点*/

{pre=k1;

k1=k1->next;

count++;

}

while(k1->next!=k1) /*当循环链表中的结点个数大于1时*/

{ p=k1; /*从k1开始报数*/

count=1;

while (count!=m) /*连续数m个结点*/

{ pre=p;

p=p->next;

count++;

}

pre->next=p->next; /*输出该结点,并删除该结点*/

printf("%4d",p->data);

free(p);

k1=pre->next; /*新的报数起点*/

}

printf("%4d",k1->data); /*输出最后一个结点*/

free(k1);

}

main()

{linklist head,p,r;

int n,s,m,i;

printf("n=");

scanf("%d",&n);

printf("s=");

2011年内蒙古自治区数据基础理论大纲

scanf("%d",&s);

printf("m=",&m);

scanf("%d",&m);

if (n<1) printf("n<0");

else

{/*建表*/

head=(linklist)malloc(sizeof(listnode)); /*建第一个结点*/

head->data=n;

r=head;

for (i=n-1;i>0;i--) /*建立剩余n-1个结点*/

{ p=(linklist)malloc(sizeof(listnode));

p->data=i;

p->next=head;

head=p;

}

r->next=head; /*生成循环链表*/

jose(head,s,m); /*调用函数*/

}

}

3、证明由二叉树的中序序列和后序序列,也可以唯一确定一棵二叉树。

当n=1时,只有一个根结点,由中序序列和后序序列可以确定这棵二叉树。

设当n=m-1时结论成立,现证明当n=m时结论成立。

设中序序列为S1,S2, ,Sm,后序序列是P1,P2, ,Pm。因后序序列最后一个元素Pm是根,则在中序序列中可找到与Pm相等的结点(设二叉树中各结点互不相同)Si(1≤i≤m),因中序序列是由中序遍历而得,所以Si是根结点,S1,S2, ,Si-1是左子树的中序序列,而Si+1,Si+2, ,Sm是右子树的中序序列。

若i=1,则S1是根,这时二叉树的左子树为空,右子树的结点数是m-1,则{S2,S3, ,Sm}和{P1,P2, ,Pm-1}可以唯一确定右子树,从而也确定了二叉树。

若i=m,则Sm是根,这时二叉树的右子树为空,左子树的结点数是m-1,则{S1,S2, ,Sm-1}和{P1,P2, ,Pm-1}唯一确定左子树,从而也确定了二叉树。

最后,当1<i<m时,Si把中序序列分成{S1,S2, ,Si-1}和{Si+1,Si+2, ,Sm}。由于后序遍历是“左子树—右子树—根结点”,所以{P1,P2, ,Pi-1}和{Pi,Pi+1, Pm-1}是二叉树的左子树和右子树的后序遍历序列。因而由{S1,S2, ,Si-1}和{P1,P2, ,Pi-1} 可唯一确定二叉树的左子树,由{Si+1,Si+2, ,Sm}和

{Pi,Pi+1, ,Pm-1}可唯一确定二叉树的右子树。

4、二叉树的层次遍历序列的第一个结点是二叉树的根。实际上,层次遍历序列中的每个结点都是“局部根”。确定根后,到二叉树的中序序列中,查到该结点,该结点将二叉树分为“左根右”三部分。若左、右子树均有,则层次序列根结点的后面应是左右子树的根;若中序序列中只有左子树或只有右子树,则在层次序列的根结点后也只有左子树的根或右子树的根。这样,定义一个全局变量指针R,指向层次序列待处理元素。算法中先处理根结点,将根结点和左右子女的信息入队列。然后,在队列不空的条件下,循环处理二叉树的结点。队列中元素的数据结构定义如下:

2011年内蒙古自治区数据基础理论大纲

typedef struct

{ int lvl; //层次序列指针,总是指向当前“根结点”在层次序列中的位置 int l,h; //中序序列的下上界

int f; //层次序列中当前“根结点”的双亲结点的指针

int lr; // 1—双亲的左子树 2—双亲的右子树

}qnode;

BiTree Creat(datatype in[],level[],int n)

//由二叉树的层次序列level[n]和中序序列in[n]生成二叉树。 n是二叉树的结点数 {if (n<1) {printf(“参数错误\n”); exit(0);}

qnode s,Q[]; //Q是元素为qnode类型的队列,容量足够大

init(Q); int R=0; //R是层次序列指针,指向当前待处理的结点

BiTree p=(BiTree)malloc(sizeof(BiNode)); //生成根结点

p->data=level[0]; p->lchild=null; p->rchild=null; //填写该结点数据

for (i=0; i<n; i++) //在中序序列中查找根结点,然后,左右子女信息入队列 if (in[i]==level[0]) break;

if (i==0) //根结点无左子树,遍历序列的1—n-1是右子树

{p->lchild=null;

s.lvl=++R; s.l=i+1; s.h=n-1; s.f=p; s.lr=2; enqueue(Q,s);

}

else if (i==n-1) //根结点无右子树,遍历序列的1—n-1是左子树

{p->rchild=null;

s.lvl=++R; s.l=1; s.h=i-1; s.f=p; s.lr=1; enqueue(Q,s);

}

else //根结点有左子树和右子树

{s.lvl=++R; s.l=0; s.h=i-1; s.f=p; s.lr=1;enqueue(Q,s);//左子树有关信息入队列 s.lvl=++R; s.l=i+1;s.h=n-1;s.f=p; s.lr=2;enqueue(Q,s);//右子树有关信息入队列 }

while (!empty(Q)) //当队列不空,进行循环,构造二叉树的左右子树

{ s=delqueue(Q); father=s.f;

for (i=s.l; i<=s.h; i++)

if (in[i]==level[s.lvl]) break;

p=(bitreptr)malloc(sizeof(binode)); //申请结点空间

p->data=level[s.lvl]; p->lchild=null; p->rchild=null; //填写该结点数据 if (s.lr==1) father->lchild=p;

else father->rchild=p; //让双亲的子女指针指向该结点

if (i==s.l)

{p->lchild=null; //处理无左子女

s.lvl=++R; s.l=i+1; s.f=p; s.lr=2; enqueue(Q,s);

}

else if (i==s.h)

{p->rchild=null; //处理无右子女

s.lvl=++R; s.h=i-1; s.f=p; s.lr=1; enqueue(Q,s);

}

else{s.lvl=++R; s.h=i-1; s.f=p; s.lr=1; enqueue(Q,s);//左子树有关信息入队

2011年内蒙古自治区数据基础理论大纲

s.lvl=++R; s.l=i+1; s.f=p; s.lr=2; enqueue(Q,s); //右子树有关信息入队列 }

}//结束while (!empty(Q))

return(p);

}//算法结束

5、二叉树的层次遍历序列的第一个结点是二叉树的根。实际上,层次遍历序列中的每个结点都是“局部根”。确定根后,到二叉树的中序序列中,查到该结点,该结点将二叉树分为“左根右”三部分。若左、右子树均有,则层次序列根结点的后面应是左右子树的根;若中序序列中只有左子树或只有右子树,则在层次序列的根结点后也只有左子树的根或右子树的根。这样,定义一个全局变量指针R,指向层次序列待处理元素。算法中先处理根结点,将根结点和左右子女的信息入队列。然后,在队列不空的条件下,循环处理二叉树的结点。队列中元素的数据结构定义如下:

typedef struct

{ int lvl; //层次序列指针,总是指向当前“根结点”在层次序列中的位置 int l,h; //中序序列的下上界

int f; //层次序列中当前“根结点”的双亲结点的指针

int lr; // 1—双亲的左子树 2—双亲的右子树

}qnode;

BiTree Creat(datatype in[],level[],int n)

//由二叉树的层次序列level[n]和中序序列in[n]生成二叉树。 n是二叉树的结点数 {if (n<1) {printf(“参数错误\n”); exit(0);}

qnode s,Q[]; //Q是元素为qnode类型的队列,容量足够大

init(Q); int R=0; //R是层次序列指针,指向当前待处理的结点

BiTree p=(BiTree)malloc(sizeof(BiNode)); //生成根结点

p->data=level[0]; p->lchild=null; p->rchild=null; //填写该结点数据

for (i=0; i<n; i++) //在中序序列中查找根结点,然后,左右子女信息入队列 if (in[i]==level[0]) break;

if (i==0) //根结点无左子树,遍历序列的1—n-1是右子树

{p->lchild=null;

s.lvl=++R; s.l=i+1; s.h=n-1; s.f=p; s.lr=2; enqueue(Q,s);

}

else if (i==n-1) //根结点无右子树,遍历序列的1—n-1是左子树

{p->rchild=null;

s.lvl=++R; s.l=1; s.h=i-1; s.f=p; s.lr=1; enqueue(Q,s);

}

else //根结点有左子树和右子树

{s.lvl=++R; s.l=0; s.h=i-1; s.f=p; s.lr=1;enqueue(Q,s);//左子树有关信息入队列 s.lvl=++R; s.l=i+1;s.h=n-1;s.f=p; s.lr=2;enqueue(Q,s);//右子树有关信息入队列 }

while (!empty(Q)) //当队列不空,进行循环,构造二叉树的左右子树

{ s=delqueue(Q); father=s.f;

for (i=s.l; i<=s.h; i++)

2011年内蒙古自治区数据基础理论大纲

if (in[i]==level[s.lvl]) break;

p=(bitreptr)malloc(sizeof(binode)); //申请结点空间

p->data=level[s.lvl]; p->lchild=null; p->rchild=null; //填写该结点数据 if (s.lr==1) father->lchild=p;

else father->rchild=p; //让双亲的子女指针指向该结点

if (i==s.l)

{p->lchild=null; //处理无左子女

s.lvl=++R; s.l=i+1; s.f=p; s.lr=2; enqueue(Q,s);

}

else if (i==s.h)

{p->rchild=null; //处理无右子女

s.lvl=++R; s.h=i-1; s.f=p; s.lr=1; enqueue(Q,s);

}

else{s.lvl=++R; s.h=i-1; s.f=p; s.lr=1; enqueue(Q,s);//左子树有关信息入队列

s.lvl=++R; s.l=i+1; s.f=p; s.lr=2; enqueue(Q,s); //右子树有关信息入队列 }

}//结束while (!empty(Q))

return(p);

}//算法结束

本文来源:https://www.bwwdw.com/article/kln4.html

Top