西藏自治区数据要领基础
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
西藏自治区数据要领基础
2010年西藏自治区数据要领基础
1、二路插入排序是将待排关键字序列r[1..n]中关键字分二路分别按序插入到辅助向量d[1..n]前半部和后半部(注:向量d可视为循环表),其原则为,先将r[l]赋给d,再从r 记录开始分二路插入。
编写实现二路插入排序算法。
2、本题应使用深度优先遍历,从主调函数进入dfs(v)时,开始记数,若退出dfs()前,已访问完有向图的全部顶点(设为n 个),则有向图有根,v为根结点。
将n个顶点从1到n编号,各调用一次dfs()过程,就可以求出全部的根结点。
题中有向图的邻接表存储结构、记顶点个数的变量、以及访问标记数组等均设计为全局变量。
建立有向图g的邻接表存储结构参见上面第2题,这里只给出判断有向图是否有根的算法。
int num=0,visited[]=0 //num记访问顶点个数,访问数组visited初始化。
const n=用户定义的顶点数;
AdjList g ; //用邻接表作存储结构的有向图g。
void dfs(v)
{visited [v]=1; num++; //访问的顶点数+1
if (num==n) {printf(“%d是有向图的根。
\n”,v); num=0;}//if
p=g[v].firstarc;
while (p)
{if (visied[p-adjvex]==0) dfs (p-adjvex);
p=p-next;} //while
visited[v]=0; num--; //恢复顶点v
}//dfs
void JudgeRoot()
//判断有向图是否有根,有根则输出之。
{static int i ;
for (i=1;ii++ ) //从每个顶点出发,调用dfs()各一次。
{num=0; visited[1..n]=0; dfs(i); }
}// JudgeRoot
算法中打印根时,输出顶点在邻接表中的序号(下标),若要输出顶点信息,可使用g[i].vertex。
3、4、void LinkList_reverse(Linklist L)
//链表的就地逆置;为简化算法,假设表长大于2
{
p=L-next;q=p-next;s=q-next;p-next=NULL;
while(s-next)
{
q-next=p;p=q;
q=s;s=s-next; //把L的元素逐个插入新表表头
}
q-next=p;s-next=q;L-next=s;
}//LinkList_reverse
4、设T是一棵满二叉树,编写一个将T的先序遍历序列转换为后序遍历序列的递归算法。
5、设t是给定的一棵二叉树,下面的递归程序count(t)用于求得:二叉树t中具有非空的左,右两个儿子的结点个数N2;只有非空左儿子的个数NL;只有非空右儿子的结点个数NR和叶子结点个数N0。
N2、NL、NR、N0都是全局量,且在调用count(t)之前都置为0.
typedef struct node
{int data; struct node *lchild,*rchild;}node;
int N2,NL,NR,N0;
void count(node *t)
{if (t-lchild!=NULL) if (1)___ N2++; else NL++;
else if (2)___ NR++; else (3)__ ;
if(t-lchild!=NULL)(4)____; if (t-rchild!=NULL) (5)____;
}
26.树的先序非递归算法。
void example(b)
btree *b;
{ btree *stack, *p;
int top;
if (b!=null)
{ top=1; stack[to
p]=b;
while (top0)
{ p=stack[top]; top--;
printf(“%d”,p-data);
if (p-rchild!=null)
{(1)___; (2)___;
}
if (p-lchild!=nul
2010年西藏自治区数据要领基础
l)
(3)___; (4)__;
}}}}
6、设t是给定的一棵二叉树,下面的递归程序count(t)用于求得:二叉树t中具有非空的左,右两个儿子的结点个数N2;只有非空左儿子的个数NL;只有非空右儿子的结点个数NR和叶子结点个数N0。
N2、NL、NR、N0都是全局量,且在调用count(t)之
前都置为0.
typedef struct node
{int data; struct node *lchild,*rchild;}node;
int N2,NL,NR,N0;
void count(node *t)
{if (t-lchild!=NULL) if (1)___ N2++; else NL++;
else if (2)___ NR++; else (3)__ ;
if(t-lchild!=NULL)(4)____; if (t-rchild!=NULL) (5)____;
}
26.树的先序非递归算法。
void example(b)
btree *b;
{ btree *stack, *p;
int top;
if (b!=null)
{ top=1; stack[top]=b;
while (top0)
{ p=stack[top]; top--;
printf(“%d”,p-data);
if (p-rchild!=null)
{(1)___; (2)___;
}
if (p-lchild!=null)
(3)___; (4)__;
}}}}
7、矩阵中元素按行和按列都已排序,要求查找时间复杂度为O(m+n),因此不能采用常规的二层循环的查找。
可以先从右上角(i=a,j=d)元素与x比较,只有三种情况:一是A[i,j]x,这情况下向j 小的方向继续查找;二是A[i,j]x,下步应向i大的方向查找;三是A[i,j]=x,查找成功。
否则,若下标已超出范围,则查找失败。
void search(datatype A[ ][ ], int a,b,c,d, datatype x)
//n*m矩阵A,行下标从a到b,列下标从c到d,本算法查找x 是否在矩阵A中.
{i=a; j=d; flag=0; //flag是成功查到x的标志
while(i=b j=c)
if(A[i][j]==x) {flag=1;break;}
else if (A[i][j]x) j--; else i++;
if(flag) printf(“A[%d][%d]=%d”,i,j,x); //假定x为整型.
else printf(“矩阵A中无%d 元素”,x);
}算法search结束。
[算法讨论]算法中查找x的路线从右上角开始,向下(当
xA[i,j])或向左(当xA[i,j])。
向下最多是m,向左最多是n。
最佳情况是在右上角比较一次成功,最差是在左下角(A[b,c]),比较m+n次,故算法最差时间复杂度是O(m+n)。
8、设有一组初始记录关键字序列(K1,K2,。
,Kn),要求设计一个算法能够在O(n)的时间复杂度内将线性表划分成两部分,其中左半部分的每个关键字均小于Ki,右半部分的每个关键字均大于等于Ki。
void quickpass(int r[], int s, int t)
{
int i=s, j=t, x=r[s];
while(ij){
while (ij r[j]x) j=j-1; if (ij) {r[i]=r[j];i=i+1;}
while (ij r[i]x) i=i+1; if (ij) {r[j]=r[i];j=j-1;}
}
r[i]=x;
}
9、我们用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个元素
2010年西藏自治区数据要领基础
的整型数组b中最长平台的长度。
{l=1;k=0;j=0;i=0;
while(in-1)
{while(in-1 b[i]==b[i+1]) i++;
if(i-j+1l) {l=i-j+1;k=j;} //局部最长平台
i++; j=i; } //新平台起点
printf(“最长平台长度%d,在b数组中起始下标为%d”,l,k);
}// Platform
10、给定n个村庄之间的交通图,若村庄i和j之间有道路,则将顶点i和j用边连接,边上的Wij表示这条道路的长度,现在要从这n个村庄中选择一个村庄建一所医院,问这所医院应建在哪个村庄,才能使离医院最远的村庄到医院的路程最短?试设计一个解答上述问题的算法,并应用该算法解答如图所示的实例。
(20分)
11、(1)p-rchild (2)p-lchild (3)p-lchild (4)ADDQ(Q,p-lchild) (5)ADDQ(Q,p-rchild)
25. (1)t-rchild!=null (2)t-rchild!=null (3)N0++ (4)count(t-
lchild) (5)count(t-rchild)
26. .(1)top++ (2) stack[top]=p-rchild (3)top++ (4)stack[top]=p-lchild
27. (1)*ppos // 根结点(2)rpos=ipos (3)rposCipos (4)ipos (5)ppos+1
12、设t是给定的一棵二叉树,下面的递归程序count(t)用于求得:二叉树t中具有非空的左,右两个儿子的结点个数N2;只有非空左儿子的个数NL;只有非空右儿子的结点个数NR和叶子结点个数N0。
N2、NL、NR、N0都是全局量,且在调用count(t)之前都置为0.
typedef struct node
{int data; struct node *lchild,*rchild;}node;
int N2,NL,NR,N0;
void count(node *t)
{if (t-lchild!=NULL) if (1)___ N2++; else NL++;
else if (2)___ NR++; else (3)__ ;
if(t-lchild!=NULL)(4)____; if (t-rchild!=NULL) (5)____;
}
26.树的先序非递归算法。
void example(b)
btree *b;
{ btree *stack, *p;
int top;
if (b!=null)
{ top=1; stack[top]=b;
while (top0)
{ p=stack[top]; top--;
printf(“%d”,p-data);
if (p-rchild!=null)
{(1)___; (2)___;
}
if (p-lchild!=null)
(3)___; (4)__;
}}}}
13、我们用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(in-1)
{while(in-1 b[i]==b[i+1]) i++;
if(i-j+1l) {l=i-j+1;k=j;} //局部最长平台
i++; j=i; } //新平台起点
printf(“最
长平台长度%d,在b数组中起始下标为%d”,l,k);
}// Platform
14、请设计一个算法,要求该算法把二叉树的叶子结点按从左到右的顺序连成一个单链表,表头指针为head。
二叉树按二叉链表方式存储,链接时用叶子结点的右指针域来存放单链表指针。
分析你的算法的时、空复杂
2010年西藏自治区数据要领基础
度。
15、设一棵树T中边的集合为{(A,B),(A,C),(A,D),(B,
E),(C,F),(C,G)},要求用孩子兄弟表示法(二叉链表)表示出该树的存储结构并将该树转化成对应的二叉树。
16、在有向图G中,如果r到G中的每个结点都有路径可达,则称结点r为G的根结点。
编写一个算法完成下列功能:(1).建立有向图G的邻接表存储结构;
(2).判断有向图G是否有根,若有,则打印出所有根结点的值。
17、有一种简单的排序算法,叫做计数排序(count sorting)。
这种排序算法对一个待排序的表(用数组表示)进行排序,并将排序结果存放到另一个新的表中。
必须注意的是,表中所有待排序的关键码互不相同,计数排序算法针对表中的每个记录,扫描待排序的表一趟,统计表中有多少个记录的关键码比该记录的关键码小,假设针对某一个记录,统计出的计数值为c,那么,这个记录在新的有序表中的合适的存放位置即为c。
(1) (3分)给出适用于计数排序的数据表定义;
(2) (7分)使用Pascal或C语言编写实现计数排序的算法;
(3) (4分)对于有n个记录的表,关键码比较次数是多少?
(4) (3分)与简单选择排序相比较,这种方法是否更好?为什么?
18、两棵空二叉树或仅有根结点的二叉树相似;对非空二叉树,可判左右子树是否相似,采用递归算法。
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
19、二叉树的层次遍历序列的第一个结点是二叉树的根。
实际上,层次遍历序列中的每个结点都是“局部根”。
确定根后,到二叉树的中序序列中,查到该结点,该结点将二叉树分为“左根右”三部分。
若左、右子树均有,则层次序列根结点的后面应是左右子树的根;若中序序列中只有左子树或只有右子树,则在层次序列的根结点后也只有左子树的根或右子树的根。
这样,定义一个全局变量指针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 (n1) {
2010年西藏自治区数据要领基础
printf(“参数错误\n”); exit(0);}
qnode s,Q[]; //Q是元素为qnode类型的队列,容量足够大init(Q); int R=0; //R是层次序列指针,指向当前待处理的结点
BiTree p=(BiTree)malloc(sizeof(BiNode)); //生成根结点
p-data=level; p-lchild=null; p-rchild=null; //填写该结点数据
for (i=0; i i++) //在中序序列中查找根结点,然后,左右子女信息入队列
if (in[i]==level) 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);//左子树有关信息入队列
s.lvl=++R; s.l=i+1; s.f=p; s.lr=2; enqueue(Q,s); //右子树有关信息入队列
}
}//结束while (!empty(Q))
return(p);
}//算法结束
20、在有向图G中,如果r到G中的每个结点都有路径可达,则称结点r为G的根结点。
编写一个算法完成下列功能:(1).建立有向图G的邻接表存储结构;
(2).判断有向图G是否有根,若有,则打印出所有根结点的值。
21、后序遍历最后访问根结点,即在递归算法中,根是压在栈底的。
采用后序非递归算法,栈中存放二叉树结点的指针,当访问到某结点时,栈中所有元素均为该结点的祖先。
本题要找p 和q 的最近共同祖先结点r ,不失一般性,设p在q的左边。
后序遍历必然先遍历到结点p,栈中元素均为p的祖先。
将栈拷入另一辅助栈中。
再继续遍历到结点q时,
将栈中元素从栈顶开始逐个到辅助栈中去匹配,第一个匹配(即相等)的元素就是结点p 和q的最近公共祖先。
typedef struct
{BiTree t;int tag;//tag=0 表示结点的左子女已被访问,tag=1表示结点的右子女已被访问
}stack;
stack s[
2010年西藏自治区数据要领基础
],s1[];//栈,容量够大
BiTree Ancestor(BiTree ROOT,p,q,r)//求二叉树上结点p和q 的最近的共同祖先结点r。
{top=0; bt=ROOT;
while(bt!=null ||top0)
{while(bt!=null bt!=p bt!=q) //结点入栈
{s[++top].t=bt; s[top].tag=0; bt=bt-lchild;} //沿左分枝向下if(bt==p) //不失一般性,假定p在q的左侧,遇结点p时,栈中元素均为p的祖先结点
{for(i=1;i=top;i++) s1[i]=s[i]; top1=top; }//将栈s的元素转入辅助栈s1 保存
if(bt==q) //找到q 结点。
for(i=top;ii--)//;将栈中元素的树结点到s1去匹配
{pp=s[i].t;
for (j=top1;jj--)
if(s1[j].t==pp) {printf(“p 和q的最近共同的祖先已找到”);return (pp);}
}
while(top!=0 s[top].tag==1) top--; //退栈
if (top!=0){s[top].tag=1;bt=s[top].t-rchild;}//沿右分枝向下遍历
}//结束while(bt!=null ||top0)
return(null);//q、p无公共祖先
}//结束Ancestor
22、后序遍历最后访问根结点,即在递归算法中,根是压在栈底的。
采用后序非递归算法,栈中存放二叉树结点的指针,当访问到某结点时,栈中所有元素均为该结点的祖先。
本题要找p 和q 的最近共同祖先结点r ,不失一般性,设p在q的左边。
后序遍历必然先遍历到结点p,栈中元素均为p的祖先。
将栈拷入另一辅助栈中。
再继续遍历到结点q时,将栈中元素从栈顶开始逐个到辅助栈中去匹配,第一个匹配(即相等)的元素就是结点p 和q的最近公共祖先。
typedef struct
{BiTree t;int tag;//tag=0 表示结点的左子女已被访问,tag=1
表示结点的右子女已被访问
}stack;
stack s[],s1[];//栈,容量够大
BiTree Ancestor(BiTree ROOT,p,q,r)//求二叉树上结点p和q 的最近的共同祖先结点r。
{top=0; bt=ROOT;
while(bt!=null ||top0)
{while(bt!=null bt!=p bt!=q) //结点入栈
{s[++top].t=bt; s[top].tag=0; bt=bt-lchild;} //沿左分枝向下if(bt==p) //不失一般性,假定p在q的左侧,遇结点p时,栈中元素均为p的祖先结点
{for(i=1;i=top;i++) s1[i]=s[i]; top1=top; }//将栈s的元素转入辅助栈s1 保存
if(bt==q) //找到q 结点。
for(i=top;ii--)//;将栈中元素的树结点到s1去匹配
{pp=s[i].t;
for (j=top1;jj--)
if(s1[j].t==pp) {printf(“p 和q的最近共同的祖先已找到”);return (pp);}
}
while(top!=0 s[top].tag==1) top--; //退栈
if (top!=0){s[top].tag=1;bt=s[top].t-rchild;}//沿右分枝向下遍历
}//结束while(bt!=null ||top0)
return(null);//q、p无公共祖先
}//
结束Ancestor
23、设有一个数组中存放了一个无序的关键序列K1、K2、。
、Kn。
现要求将Kn放在将元素排序后的正确位置上,试编写实现该功能的算法,要求比较关键字的次数不超过n。
51. 借助于快速排序的算法思想,在一组无序的记录中查找给定关键字值等于key的记录。
设此组记
2010年西藏自治区数据要领基础
录存放于数组r[l..h]中。
若查找成功,则输出该记录在r数组中的位置及其值,否则显示“not find”信息。
请编写出算法并简要说明算法思想。
24、有一种简单的排序算法,叫做计数排序(count sorting)。
这种排序算法对一个待排序的表(用数组表示)进行排序,并将排序结果存放到另一个新的表中。
必须注意的是,表中所有待排序的关键码互不相同,计数排序算法针对表中的每个记录,扫描待排序的表一趟,统计表中有多少个记录的关键码比该记录的关键码小,假设针对某一个记录,统计出的计数值为c,那么,这个
记录在新的有序表中的合适的存放位置即为c。
(1) (3分)给出适用于计数排序的数据表定义;
(2) (7分)使用Pascal或C语言编写实现计数排序的算法;
(3) (4分)对于有n个记录的表,关键码比较次数是多少?
(4) (3分)与简单选择排序相比较,这种方法是否更好?为什么?
25、请编写一个判别给定二叉树是否为二叉排序树的算法,设二叉树用llink-rlink法存储。
26、矩阵中元素按行和按列都已排序,要求查找时间复杂度为O(m+n),因此不能采用常规的二层循环的查找。
可以先从右上角(i=a,j=d)元素与x比较,只有三种情况:一是A[i,j]x,这情况下向j 小的方向继续查找;二是A[i,j]x,下步应向i大的方向查找;三是A[i,j]=x,查找成功。
否则,若下标已超出范围,则查找失败。
void search(datatype A[ ][ ], int a,b,c,d, datatype x)
//n*m矩阵A,行下标从a到b,列下标从c到d,本算法查找x 是否在矩阵A中.
{i=a; j=d; flag=0; //flag是成功查到x的标志
while(i=b j=c)
if(A[i][j]==x) {flag=1;break;}
else if (A[i][j]x) j--; else i++;
if(flag) print f(“A[%d][%d]=%d”,i,j,x); //假定x为整型.
else printf(“矩阵A中无%d 元素”,x);
}算法search结束。
[算法讨论]算法中查找x的路线从右上角开始,向下(当xA[i,j])或向左(当xA[i,j])。
向下最多是m,向左最多是n。
最佳情况是在右上角比较一次成功,最差是在左下角(A[b,c]),比较m+n次,故算法最差时间复杂度是O(m+n)。
27、假设以I和O分别表示入栈和出栈操作。
栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。
(15分)(1)A和D是合法序列,B和C 是非法序列。
(2)设被判定的操作序列已存入一维数组A中。
int Judge(char A[])
//判断字符数组A中的输入输出序列是否是合法序列。
如是,返回true,否则返回false。
{i=0; //i为下标。
j=k=0; //j和k分别为I和字母O的的个数。
while(A[i]!=‘\0’) //当未到字符
2010年西藏自治区数据要领基础
数组尾就作。
{switch(A[i])
{case‘I’: j++; break; //入栈次数增1。
case‘O’: k++; if(kj){printf(“序列非法\n”);exit(0);}
}
i++; //不论A[i]是‘I’或‘O’,指针i均后移。
}
if(j!=k) {printf(“序列非法\n”);return(false);}
else {printf(“序列合法\n”);return(true);}
}//算法结束。
28、#define maxsize 栈空间容量
void InOutS(int s[maxsize])
//s是元素为整数的栈,本算法进行入栈和退栈操作。
{int top=0; //top为栈顶指针,定义top=0时为栈空。
for(i=1; i i++) //n个整数序列作处理。
{scanf(“%d”, //从键盘读入整数序列。
if(x!=-1) // 读入的整数不等于-1时入栈。
if(top==maxsize-1){printf(“栈满\n”);exit(0);}
else s[++top]=x; //x入栈。
else //读入的整数等于-1时退栈。
{if(top==0){printf(“栈空\n”);exit(0);}
else printf(“出栈元素是%d\n”,s[top--]);}
}
}//算法结
29、根据二叉排序树中序遍历所得结点值为增序的性质,在遍历中将当前遍历结点与其前驱结点值比较,即可得出结论,为此设全局指针变量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-datat-data)pre=t;//前驱指针指向当前结点else{flag=flase;} //不是完全二叉树
Judgebst (t-rlink,flag);// 中序遍历右子树
}//JudgeBST算法结束
30、设有一个数组中存放了一个无序的关键序列K1、K2、。
、Kn。
现要求将Kn放在将元素排序后的正确位置上,试编写实现该功能的算法,要求比较关键字的次数不超过n。
51. 借助于快速排序的算法思想,在一组无序的记录中查找给定关键字值等于key的记录。
设此组记录存放于数组r[l..h]中。
若查找成功,则输出该记录在r数组中的位置及其值,否则显示“not find”信息。
请编写出算法并简要说明算法思想。
31、4、void LinkList_reverse(Linklist L)
//链表的就地逆置;为简化算法,假设表长大于2
{
p=L-next;q=p-next;s=q-next;p-next=NULL;
while(s-next)
{
q-next=p;p=q;
q=s;s=s-next; //把L的元素逐个插入新
2010年西藏自治区数据要领基础
表表头
}
q-next=p;s-next=q;L-next=s;
}//LinkList_reverse
32、假设以I和O分别表示入栈和出栈操作。
栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。
(15分)(1)A和D是合法序列,B和C 是非法序列。
(2)设被判定的操作序列已存入一维数组A中。
int Judge(char A[])
//判断字符数组A中的输入输出序列是否是合法序列。
如是,返回true,否则返回false。
{i=0; //i为下标。
j=k=0; //j和k分别为I和字母O的的个数。
while(A[i]!=‘\0’) //当未到字符数组尾就作。
{switch(A[i])
{case‘I’: j++; break; //入栈次数增1。
case‘O’: k++; if(kj){printf(“序列非法\n”);exit(0);}
}
i++; //不论A[i]是‘I’或‘O’,指针i均后移。
}
if(j!=k) {printf(“序列非法\n”);return(false);}
else {printf(“序列合法\n”);return(true);}
}//算法结束。
33、若第n件物品能放入背包,则问题变为能否再从n-1件物品中选出若干件放入背包(这时背包可放入物品的重量变为s-w[n])。
若第n件物品不能放入背包,则考虑从n-1件物品选若干件放入背包(这时背包可放入物品仍为s)。
若最终s=0,则有一解;否则,若s0或虽然s0但物品数n1,则无解。
(1)s-w[n],n-1 //Knap(s-w[n],n-1)=true
(2)s,n-1 // Knap←Knap(s,n-1)
34、对一般二叉树,仅根据一个先序、中序、后序遍历,不能确定另一个遍历序列。
但对于满二叉树,任一结点的左右子树均含有数量相等的结点,根据此性质,可将任一遍历序列转为另一遍历序列(即任一遍历序列均可确定一棵二叉树)。
void PreToPost(ElemType pre[] ,post[],int l1,h1,l2,h2)
//将满二叉树的先序序列转为后序序列,l1,h1,l2,h2是序列初始和最后结点的下标。
{if(h1=l1)
{post[h2]=pre[l1]; //根结点
half=(h1-l1)/2; //左或右子树的结点数
PreToPost(pre,post,l1+1,l1+half,l2,l2+half-1) //将左子树先序序列转为后序序列
PreToPost(pre,post,l1+half+1,h1,l2+half,h2-1) //将右子树先序序列转为后序序列
} }//PreToPost
32. .叶子结点只有在遍历中才能知道,这里使用中序递归遍历。
设置前驱结点指针pre,初始为空。
第一个叶子结点由指针head指向,遍历到叶子结点时,就将它前驱的rchild指针指向它,最后叶子结点的rchild为空。
LinkedList head,pre=null; //全局变量
LinkedList InOrder(BiTree bt)
//中
序遍历二叉树bt,将叶子结点从左到右链成一个单链表,表头指针为head
{if(bt){InOrder(bt-lchild); //中序遍历左子树
if(bt-lchild==null bt-rchild==null)
2010年西藏自治区数据要领基础
//叶子结点
if(pre==null) {head=bt; pre=bt;} //处理第一个叶子结点
else{pre-rchild=bt; pre=bt; } //将叶子结点链入链表
InOrder(bt-rchild); //中序遍历左子树
pre-rchild=null; //设置链表尾
}
return(head); } //InOrder
时间复杂度为O(n),辅助变量使用head和pre,栈空间复杂度O(n)
35、设一组有序的记录关键字序列为(13,18,24,35,47,50,62,83,90),查找方法用二分查找,要求计算出查找关键字62时的比较次数并计算出查找成功时的平均查找长度。
36、设指针变量p指向双向链表中结点A,指针变量q指向被插入结点B,要求给出在结点A的后面插入结点B的操作序列
(设双向链表中结点的两个指针域分别为llink和rlink)。
37、假设以I和O分别表示入栈和出栈操作。
栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。
(15分)(1)A和D是合法序列,B和C 是非法序列。
(2)设被判定的操作序列已存入一维数组A中。
int Judge(char A[])
//判断字符数组A中的输入输出序列是否是合法序列。
如是,返回true,否则返回false。
{i=0; //i为下标。
j=k=0; //j和k分别为I和字母O的的个数。
while(A[i]!=‘\0’) //当未到字符数组尾就作。
{switch(A[i])
{case‘I’: j++; break; //入栈次数增1。
case‘O’: k++; if(kj){printf(“序列非法\n”);exit(0);}
}
i++; //不论A[i]是‘I’或‘O’,指针i均后移。
}
if(j!=k) {printf(“序列非法\n”);return(false);}
else {printf(“序列合法\n”);return(true);}
}//算法结束。
38、设指针变量p指向双向链表中结点A,指针变量q指向
被插入结点B,要求给出在结点A的后面插入结点B的操作序列(设双向链表中结点的两个指针域分别为llink和rlink)。
39、有一个带头结点的单链表,每个结点包括两个域,一个是整型域info,另一个是指向下一个结点的指针域next。
假设单链表已建立,设计算法删除单链表中所有重复出现的结点,使得info域相等的结点只保留一个。
#include stdio.h
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;
2010年西藏自治区数据要领基础
}
else
{ s=q; /*找与P结点值相同的结点*/
q=q-next;
}
p=p-next;
}
return head;
}
40、设有一个数组中存放了一个无序的关键序列K1、K2、。
、Kn。
现要求将Kn放在将元素排序后的正确位置上,试编写实现该功能的算法,要求比较关键字的次数不超过n。
51. 借助于快速排序的算法思想,在一组无序的记录中查找给定关键字值等于key的记录。
设此组记录存放于数组r[l..h]中。
若查找成功,则输出该记录在r数组中的位置及其值,否则显示“not find”信息。
请编写出算法并简要说明算法思想。
41、请编写一个判别给定二叉树是否为二叉排序树的算法,设二叉树用llink-rlink法存储。
42、根据二叉排序树中序遍历所得结点值为增序的性质,在遍历中将当前遍历结点与其前驱结点值比较,即可得出结论,为此设全局指针变量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-datat-data)pre=t;//前驱指针指向当前结点
else{flag=flase;} //不是完全二叉树
Judgebst (t-rlink,flag);// 中序遍历右子树
}//JudgeBST算法结束
43、约瑟夫环问题(Josephus问题)是指编号为1、2、。
,n 的n(n0)个人按顺时针方向围坐成一圈,现从第s个人开始按顺时针方向报数,数到第m个人出列,然后从出列的下一个人重新开始报数,数到第m的人又出列,。
,如此重复直到所有的人全部出列为止。
现要求采用循环链表结构设计一个算法,模拟此过程。
#includestdlib.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
2010年西藏自治区数据要领基础
(k1);。