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\ free(p);
k1=pre->next; /*新的报数起点*/ }
printf(\"%4d\输出最后一个结点*/ free(k1); }
main()
{linklist head,p,r; int n,s,m,i; printf(\"n=\"); scanf(\"%d\ printf(\"s=\"); scanf(\"%d\ printf(\"m=\ scanf(\"%d\
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); /*调用函数*/ } }
8、两棵空二叉树或仅有根结点的二叉树相似;对非空二叉树,可判左右子树是否相似,采用递归算法。
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
9、约瑟夫环问题(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\ free(p);
k1=pre->next; /*新的报数起点*/ }
printf(\"%4d\输出最后一个结点*/ free(k1); }
main()
{linklist head,p,r; int n,s,m,i; printf(\"n=\"); scanf(\"%d\ printf(\"s=\"); scanf(\"%d\ printf(\"m=\ scanf(\"%d\
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); /*调用函数*/ } }
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、已知有向图G=(V,E),其中V={V1,V2,V3,V4,V5,V6,V7},E={,,,,,,,,} 写出G的拓扑排序的结果。G拓扑排序的结果是:V1、V2、V4、V3、V5、V6、V7
12、 二叉树的层次遍历序列的第一个结点是二叉树的根。实际上,层次遍历序列中的每个结点都是“局部根”。确定根后,到二叉树的中序序列中,查到该结点,该结点将二叉树分为“左根右”三部分。若左、右子树均有,则层次序列根结点的后面应是左右子树的根;若中序序列中只有左子树或只有右子树,则在层次序列的根结点后也只有左子树的根或右子树的根。这样,定义一个全局变量指针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; iif (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); }//算法结束
13、我们可用“破圈法”求解带权连通无向图的一棵最小代价生成树。所谓“破圈法”就是“任取一圈,去掉圈上权最大的边”,反复执行这一步骤,直到没有圈为止。请给出用“破圈法”求解给定的带权连通无向图的一棵最小代价生成树的详细算法,并用程序实现你所给出的算法。注:圈就是回路。
14、给出折半查找的递归算法,并给出算法时间复杂度性分析。
15、对二叉树的某层上的结点进行运算,采用队列结构按层次遍历最适宜。
int LeafKlevel(BiTree bt, int k) //求二叉树bt 的第k(k>1) 层上叶子结点个数 {if(bt==null || k<1) return(0);
BiTree p=bt,Q[]; //Q是队列,元素是二叉树结点指针,容量足够大
int front=0,rear=1,leaf=0; //front 和rear是队头和队尾指针, leaf是叶子结点数 int last=1,level=1; Q[1]=p; //last是二叉树同层最右结点的指针,level 是二叉树的层数
while(front<=rear) {p=Q[++front];
if(level==k && !p->lchild && !p->rchild) leaf++; //叶子结点 if(p->lchild) Q[++rear]=p->lchild; //左子女入队 if(p->rchild) Q[++rear]=p->rchild; //右子女入队
if(front==last) {level++; //二叉树同层最右结点已处理,层数增1 last=rear; } //last移到指向下层最右一元素 if(level>k) return (leaf); //层数大于k 后退出运行 }//while }//结束LeafKLevel