二.2王道课后题
第三部分
15
与14题的区别是,并不产生新的单链表而是存在于a中
问题:a中是只存交集元素,还是存额外的b中的.
我选1
注意释放不是公共的结点
我选用头插法,可以不设置尾指针
代码
void combineRepeatInA(LinkList &a,LinkList &b){
LNode *p=a->next;
LNode *q=b->next;
LNode *r=NULL;//用来保证不断链的,只需一个即可,可重复利用
a->next=NULL;
//完善
//while(p!=NULL && q!=NULL){
while(p && q){
if(p->data<(q->data)){
r=p->next;
free(p);
p=r;
}
else if(p->data>q->data){
r=q->next;
free(q);
q=r;
}
else if(p->data==q->data){
r=p->next;
//头插法
p->next=a->next;
a->next=p;
p=r;
//删除q
r=q->next;
free(q);
q=r;
}
}
while(p!=NULL){ //释放p中剩余的
r=p->next;
free(p);
p=r;
}
while(q!=NULL){//释放q中剩余的
r=q->next;
free(q);
q=r;
}
free(b); //释放b头结点
}
演示
LinkList l;
initList_H(l);
insertListByOrder_H(l,1,2);
insertListByOrder_H(l,2,2);
insertListByOrder_H(l,3,3);
insertListByOrder_H(l,4,4);
insertListByOrder_H(l,5,5);
insertListByOrder_H(l,6,6);
printList_H(l);
cout<<"单链表2"<<endl;
LinkList l2;
initList_H(l2);
insertListByOrder_H(l2,1,1);
insertListByOrder_H(l2,2,3);
insertListByOrder_H(l2,3,4);
insertListByOrder_H(l2,4,9);
insertListByOrder_H(l2,5,12);
printList_H(l2);
combineRepeatInA(l,l2);
cout<<"重复的"<<endl;
printList_H(l);
//因为不存在,所以执行下面语句会报错
// if(!isEmpty(l2)){
// cout<<"l2"<<endl;
// printList_H(l2);
// }else{
// cout<<"l2为空"<<endl;
// }
结果
链表的第1个值是:2
单链表的第2个值是:2
单链表的第3个值是:3
单链表的第4个值是:4
单链表的第5个值是:5
单链表的第6个值是:6
单链表2
单链表的第1个值是:1
单链表的第2个值是:3
单链表的第3个值是:4
单链表的第4个值是:9
单链表的第5个值是:12
重复的
单链表的第1个值是:4
单链表的第2个值是:3
16
连续子序列是什么意思??是结点都连续相同,还是内容连续相同?
答:数据相同
连续子序列,怎么查找?
由于问的是b是a的连续子系列,从b的第一个位到最后的时候,必须全都包括在a中
可通过取消注释的代码,尝试不匹配的情况
在学习字符串的匹配后,可优化此过程
代码
bool isSubSequence(LinkList &a,LinkList &b){
LNode *p=a->next;
LNode *q=b->next;
LNode *r=p;//记录a中不匹配的位置
while(p){
if(p->data==q->data){
p=p->next;
q=q->next;
//优化,最后比较,只比较一次
// if(q==NULL){
// return true; //b到头了,说明全找到了
// }
}else{
r=r->next;
p=r; //a回到上次匹配的位置
q=b->next;//b回到最初位置
}
}
if(q==NULL){
return true;
}
return false;
}
演示
LinkList l;
initList_H(l);
insertListByOrder_H(l,1,2);
insertListByOrder_H(l,2,2);
insertListByOrder_H(l,3,3);
insertListByOrder_H(l,4,4);
insertListByOrder_H(l,5,5);
insertListByOrder_H(l,6,6);
printList_H(l);
cout<<"单链表2"<<endl;
LinkList l2;
initList_H(l2);
// insertListByOrder_H(l2,1,1);
// insertListByOrder_H(l2,2,3);
// insertListByOrder_H(l2,3,4);
// insertListByOrder_H(l2,4,9);
// insertListByOrder_H(l2,5,12);
insertListByOrder_H(l2,1,4);
insertListByOrder_H(l2,2,5);
insertListByOrder_H(l2,3,6);
printList_H(l2);
cout<<"b是a的连续子序列?"<<isSubSequence(l,l2)<<endl;
结果
单链表的第1个值是:2
单链表的第2个值是:2
单链表的第3个值是:3
单链表的第4个值是:4
单链表的第5个值是:5
单链表的第6个值是:6
单链表2
单链表的第1个值是:4
单链表的第2个值是:5
单链表的第3个值是:6
b是a的连续子序列?1
17
这是一个循环双链表
头尾结点怎么找?
第一个结点是头结点后面的,最后一个结点是头结点前面的
中间结点怎么找?
(1)先获取长度,判断奇数还是偶数长
或者通过判断
head!=tail && head->next!=tail
可以通过取消注释代码,查看不对称的情况
由于需要补充双链表的以下代码,可以优化
//向后遍历,跳过头结点
void printCDList(CDLinkList l){
CDLNode *p=l->next;
int i=0;
while(!isHead_CD(l,p)){
cout<<"第"<<++i<<"个元素是"<<p->data<<endl;
p=p->next;
}
}
//判头结点
bool isHead_CD(CDLinkList l,CDLNode *p){
if(p==l){
return true;
}
return false;
}
代码
bool isSymmetry(CDLinkList a){
CDLNode *head=a->next; //从头开始
CDLNode *tail=a->prior; //从尾开始
while(head!=tail && head->next!=tail){
if(head->data!=tail->data){
return false;
}
head=head->next;
tail=tail->prior;
}
return true;
}
演示
CDLinkList l;
initCDList(l);
//生成3个节点 393
CDLNode *p=(CDLNode*)malloc(sizeof(CDLNode));
p->data=3;
p->next=NULL;
p->prior=NULL;
CDLNode *q=(CDLNode*)malloc(sizeof(CDLNode));
q->data=3;
q->next=NULL;
q->prior=NULL;
CDLNode *m=(CDLNode*)malloc(sizeof(CDLNode));
m->data=9;
m->next=NULL;
m->prior=NULL;
//三行结束后现在双链表顺序为
//相当于头插法
//l->q->m->p
//l->3->9->3
insertNextNode_CD(l,p);
insertNextNode_CD(l,m);
insertNextNode_CD(l,q);
printCDList(l);
cout<<"对称"<<isSymmetry(l)<<endl;
结果
第1个元素是3
第2个元素是9
第3个元素是3
对称1
18
找到两个循环单链表的尾结点,a尾结点->next=b b尾结点->next=a;
我链接的时候,第二个链表是跳过了头结点,答案没跳过
辅助性代码
void insertClistForInit(CLinkList &l){
l=(CLNode*)malloc(sizeof(CLNode));
l->next=l;
int a;
cout<<"输入999结束初始化"<<endl;
scanf("%d",&a);
//a=90;
while(a!=999){
CLNode *p=(CLNode*)malloc(sizeof(CLNode));
p->data=a;
p->next=l->next;
l->next=p;
scanf("%d",&a);
//a=999;
}
}
void printCList(CLinkList l){
CLNode *p=l->next;
int i=0;
while(p!=l){
cout<<"第"<<++i<<"个元素是"<<p->data<<endl;
p=p->next;
}
}
代码
void combine(CLinkList a,CLinkList b){
//优化
// CLNode *p=a->next;
// CLNode *q=b->next;
CLNode *p=a;
CLNode *q=b;
while(p->next!=a){ //找到了a的最后一个结点
p=p->next;
}
while(q->next!=a){ //找到了a的最后一个结点
q=q->next;
}
p->next=b->next;
q->next=a;
}
演示
CLinkList a;
CLinkList b;
cout<<"输入第1个循环单链表的元素"<<endl;
insertClistForInit(a);
cout<<"输入第2个循环单链表的元素"<<endl;
insertClistForInit(b);
printCList(a);
printCList(b);
combine(a,b);
cout<<"合并"<<endl;
printCList(a);
结果
输入第1个循环单链表的元素
输入999结束初始化
4
2
1
999
输入第2个循环单链表的元素
输入999结束初始化
6
3
1
999
第1个元素是1
第2个元素是2
第3个元素是4
第1个元素是1
第2个元素是3
第3个元素是6
19
代码
void printMinAndDel(CLinkList &l){
CLNode *p; //工作指针
CLNode *pre; //记录最小元素的前指针
while(l->next!=l){ //执行到只剩头结点
//注意这里的初始化
pre=l;
p=l;
while(p->next!=l){ //找到了最小的一个
if(p->next->data<pre->next->data){
pre=p;
}
p=p->next;;
}
cout<<"当前最小的是"<<pre->next->data<<endl;
CLNode *q=pre->next;
pre->next=q->next;
free(q);
}
free(l);
}
演示
CLinkList a;
cout<<"输入第1个循环单链表的元素"<<endl;
insertClistForInit(a);
printCList(a);
cout<<"ok"<<endl;
printMinAndDel(a);
结果
输入第1个循环单链表的元素
输入999结束初始化
1
4
3
9
5
999
第1个元素是5
第2个元素是9
第3个元素是3
第4个元素是4
第5个元素是1
ok
当前最小的是1
当前最小的是3
当前最小的是4
当前最小的是5
当前最小的是9