一、已有a,b两个链表,每个链表中的结点包括学号和成绩。要求把两个链表合并,并按学号升序排列
#include <stdio.h>
#include<malloc.h>
//合并两个链表
#define LEN sizeof(struct student)
struct student{
long num; //序号
int score; //分数
struct student *next;
};
struct student lista,listb;
int n,sum=0;
int main()
{
struct student *creat(void); //函数声明
struct student *insert(struct student *,struct student *);
void print(struct student *);
struct student * ahead,* bhead,* abh;
printf("input list a:\n");
ahead=creat(); //调用creat函数建立表A,返回头地址
sum+=n;
printf("input list b:\n");
bhead=creat(); // 调用creat函数建立表B,返回头地址
sum+=n;
abh=insert(ahead,bhead); //调用insert函数,将两表合并
print(abh); //输出合并后的链表
return 0;
}
//create list
struct student *creat(void){
struct student *p1,*p2,*head;
n=0;
p1=p2=(struct student*)malloc(LEN);
printf("input number & scores of student:\n");
printf("if number is 0,stop inputing. \n");
scanf("%ld,%d",&p1->num,&p1->score);
head=NULL;
while(p1->num!=0){
n=n+1;
if(n==1)
head=p1;
else
p2->next=p1;
p2=p1;
p1=(struct student *)malloc(LEN);
scanf("%ld,%d",&p1->num,&p1->score);
}
p2->next=NULL;
return (head);
}
//insert,the function is merge
struct student *insert(struct student *ah,struct student *bh)
{
struct student *pa1,*pa2,*pb1,*pb2;
pa2=pa1=ah;
pb2=pb1=bh;
do{
while((pb1->num>pa1->num) &&(pa1->next!=NULL))
{ pa2=pa1;
pa1=pa1->next;
}
if(pb1->num<=pa1->num)
{
if(ah==pa1)
ah=pb1;
else
pa2->next=pb1;
pb1=pb1->next;
pb2->next=pa1;
pa2=pb2;
pb2=pb1;
}
}while((pa1->next!=NULL)||(pa1==NULL && pb1!=NULL));
if((pb1!=NULL)&&(pb1->num>pa1->num) &&(pa1->next==NULL))
pa1->next=pb1;
return (ah);
}
//print
void print(struct student *head){
struct student *p;
printf("these are %d records:\n",sum);
p=head;
if(p!=NULL)
do{
printf("%ld %d\n",p->num,p->score);
p=p->next;
}while(p!=NULL);
}
二、将两个顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表
思路:按顺序不断取下两个顺序表表头较小的结点存入新的顺序表中。然后,看哪个表还有剩余,将剩下的部分加到新的顺序表后面
bool Merge(SeqList A,SeqList B,SeqList C){
if(A.length+B.lenght>C.length)
return false;
int i=0,i=0,k=0;
while(i<A.length && j<B.length){
if(A.data[i]<B.data[j])
C.data[k]=A.data[i];
else
C.data[i]=B.data[j];
}
while(i<A.length)
C.data[k++]=A.data[i++];
C.length=k;
return false;
}
三、给定一个含n(n>=1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。例如,数组{-5,3,2,3}中未出现的最小正整数是1;数组{1,2,3}中未出现的最小正整数是4.要求:
(1)给出算法的基本设计思想
采用空间换时间。
分配一个用于标记数组B【n】,用来记录A中是否出现了1~n个正整数,B【0】对应正整数1,B【n-1】对应正整数n,
初始化B中全部为0。由于A中含有n个整数,因此可能返回的值是1~n+1,当A中n个数恰好为1~n时返回n+1。
当数组A中出现了小于等于0或大于n的值时,会导致1~n中出现空余位置,返回结果必然在1~n中,因此对于A中出现了小于等于0或大于n的值不采取任何操作。
算法流程:从A【0】开始遍历A,若0<A[i]<=n,则令B[A[i-1]]=1;否则不做操作。对A遍历后,开始遍历数组B,若能查找到第一个满足B【i】==0的下标i,返回i+1即为结果。此时说明A中未出现的最小正整数在1~n之间。
若B【i】全部不为0,返回i+1(跳出循环时i=n,i+1=n+1)此时说明A中未出现的最小正整数时n+1
(2)根据设计思想,采用C/C++描述,并给出注释
int findMissMin(int A[],int n){
int i,*B; //标记数组
B=(iny *)malloc(sizeof(int )*n); //分配空间
mesmset(B,0,sizeof(int *)n); //赋初值为0
for(i=0;i<n;i++)
if(A[i]>0&&A[i]<=n) //若A【i】的值介于1~n,则标记数组B
B[A[i]-1]=1;
for(i=0;i<n;i++) //扫描数组B,找到目标值
if(B[i]==0) break;
return i+1; //返回结果
}
(3)说明你所设计算法的时间复杂度和空间复杂度
遍历A一次,遍历B一次,两次循环内操作位O(1),会因此时间复杂度位O(n).空间复杂度:额外分配了B【n】,空间复杂度位O(n)
四、两个整数A=a1,a2,a3...an,B=b1,b2,b3....bn序列存入两个单链表中,设计一个算法,判断序列B是否为序列A的连续子序列
思路:因为两个整数序列已经存入两个链表中,操作从两个链表的第一个结点开始,若对应数据相等,则指针后移;若对应数据不等,则从A链表上次开始比较结点的后继开始,B链表仍从第一个结点开始,直到B链表到尾表示匹配成功。
A链表到尾而B链表未到尾表示失败。
操作中应当记住A链表每次开始的结点,以便下次匹配时从其后继开始
int Pattern(LinkList A,LinkList B){
LNode *p=A; //p为A链表的工作指针,本题假定A和B均无头结点
LNode *pre=p; //pre记住每趟比较中A链表的开始结点
LNode *q=B; //q是B链表的工作指针
while( P&&q)
if(p->data==q->data){//结点值相等
p=p->next;
q=q->next;
}
else{
pre=pre->next;
p=pre; //A链表新的开始比较结点
p=B;
}
if(q==NULL)
return 1; //B是A的子序列
else
return 0; //B不是A的子序列
}
五、设计算法判断带头结点的循环双链表是否对称
思路:让p从左向右扫描,q从右向左扫描,直到他们
指向同一个结点(p==q,当循环双链表结点个数为奇数时)
或相邻(p->next=q或q->prior=p,当循环双链表中结点个数为偶数时)
为止,若他们所指结点值相等,则继续进行下去,否则返回0;若比较全部相等,则返回1
int Symmetry(DLinkList L){
DNode *p=L->next,*q=L->prior;
while(p!=q && p->next!=q)
if(p->data==q->data){
p=p->next;
q=q->prior;
}
else
return 0;
return 1;
]