文档库 最新最全的文档下载
当前位置:文档库 › 2011甘肃省数据要领加强

2011甘肃省数据要领加强

2011甘肃省数据要领加强
2011甘肃省数据要领加强

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

当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

可唯一确定二叉树的左子树,由{Si+1,Si+2,…,Sm}和

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

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

#include

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=");

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、根据二叉排序树中序遍历所得结点值为增序的性质,在遍历中将当前遍历结点与其前驱结点值比较,即可得出结论,为此设全局指针变量pre(初值为null)和全局变量flag,初值为true。若非二叉排序树,则置flag为false。

#define true 1

#define false 0

typedef struct node

{datatype data; struct node *llink,*rlink;} *BTree;

void JudgeBST(BTree t,int flag)

// 判断二叉树是否是二叉排序树,本算法结束后,在调用程序中由flag得出结论。

{ if(t!=null && flag)

{ Judgebst(t->llink,flag);// 中序遍历左子树

if(pre==null)pre=t;// 中序遍历的第一个结点不必判断

else if(pre->datadata)pre=t;//前驱指针指向当前结点

else{flag=flase;} //不是完全二叉树

Judgebst (t->rlink,flag);// 中序遍历右子树

}//JudgeBST算法结束

4、有一种简单的排序算法,叫做计数排序(count sorting)。这种排序算法对一个待排序的表(用数组表示)进行排序,并将排序结果存放到另一个新的表中。必须注意的是,表中所有待排序的关键码互不相同,计数排序算法针对表中的每个记录,扫描待排序的表一趟,统计表中有多少个记录的关键码比该记录的关键码小,假设针对某一个记录,统计出的计数值为c,那么,这个记录在新的有序表中的合适的存放位置即为c。

(1) (3分)给出适用于计数排序的数据表定义;

(2) (7分)使用Pascal或C语言编写实现计数排序的算法;

(3) (4分)对于有n个记录的表,关键码比较次数是多少?

(4) (3分)与简单选择排序相比较,这种方法是否更好?为什么?

5、两棵空二叉树或仅有根结点的二叉树相似;对非空二叉树,可判左右子树是否相似,采用递归算法。

int Similar(BiTree p,q) //判断二叉树p和q是否相似

{if(p==null && q==null) return (1);

else if(!p && q || p && !q) return (0);

else return(Similar(p->lchild,q->lchild) && Similar(p->rchild,q->rchild)) }//结束Similar

6、若第n件物品能放入背包,则问题变为能否再从n-1件物品中选出若干件放入背包(这时背包可放入物品的重量变为s-w[n])。若第n件物品不能放入背包,则考虑从n-1件物品选若干件放入背包(这时背包可放入物品仍为s)。若最终s=0,则有一解;否则,若s<0或虽然s>0但物品数n<1,则无解。

(1)s-w[n],n-1 //Knap(s-w[n],n-1)=true

(2)s,n-1 // Knap←Knap(s,n-1)

7、将顶点放在两个集合V1和V2。对每个顶点,检查其和邻接点是否在同一个集合中,如是,则为非二部图。为此,用整数1和2表示两个集合。再用一队列结构存放图中访问的顶点。 int BPGraph (AdjMatrix g)

//判断以邻接矩阵表示的图g是否是二部图。

{int s[]; //顶点向量,元素值表示其属于那个集合(值1和2表示两个集合)

int Q[];//Q为队列,元素为图的顶点,这里设顶点信息就是顶点编号。

int f=0,r,visited[]; //f和r分别是队列的头尾指针,visited[]是访问数组

for (i=1;i<=n;i++) {visited[i]=0;s[i]=0;} //初始化,各顶点未确定属于那个集合

Q[1]=1; r=1; s[1]=1;//顶点1放入集合S1

while(f

{v=Q[++f]; if (s[v]==1) jh=2; else jh=1;//准备v的邻接点的集合号

if (!visited[v])

{visited[v]=1; //确保对每一个顶点,都要检查与其邻接点不应在一个集合中

for (j=1,j<=n;j++)

if (g[v][j]==1){if (!s[j]) {s[j]=jh; Q[++r]=j;} //邻接点入队列

else if (s[j]==s[v]) return(0);} //非二部图

}//if (!visited[v])

}//while

return(1); }//是二部图

[算法讨论] 题目给的是连通无向图,若非连通,则算法要修改。

8、我们用l代表最长平台的长度,用k指示最长平台在数组b中的起始位置(下标)。用j 记住局部平台的起始位置,用i指示扫描b数组的下标,i从0开始,依次和后续元素比较,若局部平台长度(i-j)大于l时,则修改最长平台的长度k(l=i-j)和其在b中的起始位置(k=j),直到b数组结束,l即为所求。

void Platform (int b[ ], int N)

//求具有N个元素的整型数组b中最长平台的长度。

{l=1;k=0;j=0;i=0;

while(i

{while(i

if(i-j+1>l) {l=i-j+1;k=j;} //局部最长平台

i++; j=i; } //新平台起点

printf(“最长平台长度%d,在b数组中起始下标为%d”,l,k);

}// Platform

9、将顶点放在两个集合V1和V2。对每个顶点,检查其和邻接点是否在同一个集合中,如是,则为非二部图。为此,用整数1和2表示两个集合。再用一队列结构存放图中访问的顶点。 int BPGraph (AdjMatrix g)

//判断以邻接矩阵表示的图g是否是二部图。

{int s[]; //顶点向量,元素值表示其属于那个集合(值1和2表示两个集合)

int Q[];//Q为队列,元素为图的顶点,这里设顶点信息就是顶点编号。

int f=0,r,visited[]; //f和r分别是队列的头尾指针,visited[]是访问数组

for (i=1;i<=n;i++) {visited[i]=0;s[i]=0;} //初始化,各顶点未确定属于那个集合

Q[1]=1; r=1; s[1]=1;//顶点1放入集合S1

while(f

{v=Q[++f]; if (s[v]==1) jh=2; else jh=1;//准备v的邻接点的集合号

if (!visited[v])

{visited[v]=1; //确保对每一个顶点,都要检查与其邻接点不应在一个集合中

for (j=1,j<=n;j++)

if (g[v][j]==1){if (!s[j]) {s[j]=jh; Q[++r]=j;} //邻接点入队列

else if (s[j]==s[v]) return(0);} //非二部图

}//if (!visited[v])

}//while

return(1); }//是二部图

[算法讨论] 题目给的是连通无向图,若非连通,则算法要修改。

10、有一个带头结点的单链表,每个结点包括两个域,一个是整型域info,另一个是指向下一个结点的指针域next。假设单链表已建立,设计算法删除单链表中所有重复出现的结点,使得info域相等的结点只保留一个。

#include

typedef char datatype;

typedef struct node{

datatype data;

struct node * next;

} listnode;

typedef listnode* linklist;

/*--------------------------------------------*/

/* 删除单链表中重复的结点 */

/*--------------------------------------------*/

linklist deletelist(linklist head)

{ listnode *p,*s,*q;

p=head->next;

while(p)

{s=p;

q=p->next;

while(q)

if(q->data==p->data)

{s->next=q->next;free(q);

q=s->next;}

else

{ s=q; /*找与P结点值相同的结点*/

q=q->next;

}

p=p->next;

}

return head;

}

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

12、连通图的生成树包括图中的全部n个顶点和足以使图连通的n-1条边,最小生成树是边上权值之和最小的生成树。故可按权值从大到小对边进行排序,然后从大到小将边删除。每删除一条当前权值最大的边后,就去测试图是否仍连通,若不再连通,则将该边恢复。若仍连通,继续向下删;直到剩n-1条边为止。

void SpnTree (AdjList g)

//用“破圈法”求解带权连通无向图的一棵最小代价生成树。

{typedef struct {int i,j,w}node; //设顶点信息就是顶点编号,权是整型数

node edge[];

scanf( "%d%d",&e,&n) ; //输入边数和顶点数。

for (i=1;i<=e;i++) //输入e条边:顶点,权值。

scanf("%d%d%d" ,&edge[i].i ,&edge[i].j ,&edge[i].w);

for (i=2;i<=e;i++) //按边上的权值大小,对边进行逆序排序。

{edge[0]=edge[i]; j=i-1;

while (edge[j].w

edge[j+1]=edge[0]; }//for

k=1; eg=e;

while (eg>=n) //破圈,直到边数e=n-1.

{if (connect(k)) //删除第k条边若仍连通。

{edge[k].w=0; eg--; }//测试下一条边edge[k],权值置0表示该边被删除k++; //下条边

}//while

}//算法结束。

connect()是测试图是否连通的函数,可用图的遍历实现,

13、请编写一个判别给定二叉树是否为二叉排序树的算法,设二叉树用llink-rlink法存储。

14、在有向图G中,如果r到G中的每个结点都有路径可达,则称结点r为G的根结点。编写一个算法完成下列功能:

(1).建立有向图G的邻接表存储结构;

(2).判断有向图G是否有根,若有,则打印出所有根结点的值。

15、我们用l代表最长平台的长度,用k指示最长平台在数组b中的起始位置(下标)。用j 记住局部平台的起始位置,用i指示扫描b数组的下标,i从0开始,依次和后续元素比较,若局部平台长度(i-j)大于l时,则修改最长平台的长度k(l=i-j)和其在b中的起始位置(k=j),直到b数组结束,l即为所求。

void Platform (int b[ ], int N)

//求具有N个元素的整型数组b中最长平台的长度。

{l=1;k=0;j=0;i=0;

while(i

{while(i

if(i-j+1>l) {l=i-j+1;k=j;} //局部最长平台

i++; j=i; } //新平台起点

printf(“最长平台长度%d,在b数组中起始下标为%d”,l,k);

}// Platform

相关文档