二.2王道课后题
第二部分
8
常规思路是暴力解法时间复杂度o(len1*len2)
我的代码和书上代码不一样,但是理念一样
假如两个链表有公共结点那么,一定在某个结点开始,一直到最后一个结点,都是公共的.
也就是从最后一个结点开始,往前n个结点是相同的.
只要先知道两个链表的长度,然后在长度相同的时候同时遍历,next相同就找到了.
时间复杂度o(len1+len2)
代码
//在结点后插入结点的方法
bool insertOrder(LNode *l,int num,LNode *q){
/* 头节点不插入值 所以插入位置只能从1开始
if (num==0){
l->data=e;
} */
if(num<1){
cout<<"位序有误"<<endl;
return false;
}
/* 第一个节点 应该位序是0
int i=1;
LNode *p=l; */
int i=0;
LNode *p =l;
//找到第i-1个位置,好来插入
//插入第一个节点 可以直接找到第0个位置
while(i<(num-1)&&p!=NULL){
p=p->next;
i++;
}
//注意别忘了这个 插入了不存在的位置 num大于长度
if(p==NULL){
cout<<"位序有误"<<endl;
return false;
}
q->next=p->next;
p->next=q;
return true;
}
LNode* findCommonLNode(LinkList &l1,LinkList &l2){
int len1=length_H(l1);
int len2=length_H(l2);
int i;
int j; //长度差
LNode *p;
LNode *q;
if(len1>=len2){ //先遍历l1 长度差
j=len1-len2;
i=0;
p=l1->next;
while(i<j){
p=p->next;
i++;
}
q=l2->next;
//此时假如第一个就相同,就会找到第二个长度相同的
//while(p->next!=q->next&&p!=NULL){
while(p!=q&&p!=NULL){
p=p->next;
q=q->next;
}
return p;
}
//if(len1<len2){ // 未返回 非1长 肯定2长
j=len2-len1;
i=0;
q=l2->next;
while(i<j){
q=q->next;
i++;
}
p=l1->next;
while(p!=q&&p!=NULL){
p=p->next;
q=q->next;
}
return p; //找不到一定在末尾,返回NULL
//}
// return
}
演示
LinkList l;
initList_H(l);
LinkList n;
initList(n); //通过初始化不带头结点的链表
insertListByOrder(n,1,99);
insertListByOrder_H(l,1,1);
insertListByOrder_H(l,2,8);
insertListByOrder_H(l,3,9);
insertOrder(l,4,n);
insertListByOrder_H(l,5,5);
printList_H(l);
LinkList l2;
initList_H(l2);
insertListByOrder_H(l2,1,1);
insertListByOrder_H(l2,2,4);
insertListByOrder_H(l2,3,3);
insertListByOrder_H(l2,4,2);
insertListByOrder_H(l2,5,5);
//insertOrder(l2,5,n); //有公共结点
cout<<"---------------"<<endl;
printList_H(l2);
// reverse01(l);
if(findCommonLNode(l,l2)!=NULL){
cout<<"公共结点"<<findCommonLNode(l,l2)->data<<endl;
}else{
cout<<"无公共结点"<<endl;
}
结果
未注释
单链表的第1个值是:1
单链表的第2个值是:8
单链表的第3个值是:9
单链表的第5个值是:5
---------------
单链表的第1个值是:1
单链表的第2个值是:4
单链表的第3个值是:3
单链表的第4个值是:2
单链表的第5个值是:99
单链表的第6个值是:5
公共结点99
注释后
单链表的第1个值是:1
单链表的第2个值是:8
单链表的第3个值是:9
单链表的第4个值是:99
单链表的第5个值是:5
---------------
单链表的第1个值是:1
单链表的第2个值是:4
单链表的第3个值是:3
单链表的第4个值是:2
单链表的第5个值是:5
无公共结点
9
此题暴力解法
和王道 不同,理念一样
代码
void minDel(LinkList &l){
// int len=length_H(l);比通过长度控制循环要好一点
while(l->next!=NULL){
LNode *pre=l->next; //工作指针,指向前一个
LNode *minpre=l; //最小元素前一个
//找到最小的注意 要用next
while(pre->next!=NULL){
if(pre->next->data<minpre->next->data){
minpre=pre;
}
pre=pre->next;
}
LNode *q=minpre->next;
int i=1;
cout<<"第"<<i++<<"个最小的是"<<minpre->next->data<<endl;
minpre->next=minpre->next->next;
free(q);
//len--;
}
free(l);
}
演示
LinkList l;
initList_H(l);
insertListByOrder_H(l,1,1);
insertListByOrder_H(l,2,4);
insertListByOrder_H(l,3,3);
insertListByOrder_H(l,4,2);
insertListByOrder_H(l,5,5);
printList_H(l);
// reverse01(l);
minDel(l);
cout<<"删除后"<<endl;
if(isEmpty_H(l)){
printList_H(l);
}else{
cout<<"空"<<endl;
}
结果
单链表的第1个值是:1
单链表的第2个值是:4
单链表的第3个值是:3
单链表的第4个值是:2
单链表的第5个值是:5
第1个最小的是1
第1个最小的是2
第1个最小的是3
第1个最小的是4
第1个最小的是5
删除后
空
10
代码
//相对位置不变,不能用头插法
LinkList divide(LinkList &l){
int i=1;
LNode *p=l->next; //工作指针
LinkList B;
B=(LinkList)malloc(sizeof(LNode));
B->next=NULL;
LNode *ra=l;
LNode *rb=B;
l->next=NULL;
while(p!=NULL){
if(i%2==1){ //奇数
ra->next=p;
ra=p;
}
if(i%2==0){ //偶数
rb->next=p;
rb=p;
}
p=p->next;
i++;
}
ra->next=NULL;
rb->next=NULL;
return B;
}
演示
LinkList l;
initList_H(l);
insertListByOrder_H(l,1,1);
insertListByOrder_H(l,2,2);
insertListByOrder_H(l,3,3);
insertListByOrder_H(l,4,4);
insertListByOrder_H(l,5,5);
printList_H(l);
cout<<"偶数 2"<<endl;
printList_H(divide(l));
cout<<"奇数 l"<<endl;
printList_H(l);
结果
单链表的第1个值是:1
单链表的第2个值是:2
单链表的第3个值是:3
单链表的第4个值是:4
单链表的第5个值是:5
偶数 2
单链表的第1个值是:2
单链表的第2个值是:4
奇数 l
单链表的第1个值是:1
单链表的第2个值是:3
单链表的第3个值是:5
因为第一个是奇数,下一个若存在,必是偶数所以,可以先奇数操作,再偶数操作
就可以不用判断奇偶数
LinkList divide02(LinkList &l){
LNode *p=l->next; //工作指针
LinkList B;
B=(LinkList)malloc(sizeof(LNode));
B->next=NULL;
LNode *ra=l; //尾指针,用于尾插法
LNode *rb=B; //尾指针
l->next=NULL;
while(p!=NULL){
ra->next=p;
ra=p;
p=p->next;
if(p!=NULL){
rb->next=p;
rb=p;
p=p->next;
}
}
ra->next=NULL;
rb->next=NULL;
return B;
}
11
这题和上面的差不多,唯一区别就是用了头插法
注释掉的部分,是我写的,也可以实现此函数,但没有书上的简练
代码
LinkList divideReverse(LinkList &l){
LNode *p=l->next;
l->next=NULL; //可不写,因为最后补充了NULL;
LinkList B=NULL;
B=new LNode; //B头结点 分配空间
B->next=NULL; //初始化
LNode *r;//原链表 不断链
LNode *m=l;//尾插法的尾指针
/* while(p!=NULL){
r=p->next;
//LNode *q=new LNode;
m->next=p;
m=p;
if(r!=NULL){
p=r->next;
r->next=B->next;
B->next=r;
}
else{
p=p->next;
}
} */
while(p!=NULL){
m->next=p;
m=p;
p=p->next;
if(p!=NULL){
r=p->next;
p->next=B->next;
B->next=p;
p=r;
}
}
m->next=NULL;
return B;
}
可以通过取消注释的那一行试一下,单数和偶数的不同
演示
LinkList l;
initList_H(l);
insertListByOrder_H(l,1,1);
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;
printList_H(divideReverse(l));
cout<<"奇数 l"<<endl;
printList_H(l);
结果
单链表的第1个值是:1
单链表的第2个值是:2
单链表的第3个值是:3
单链表的第4个值是:4
单链表的第5个值是:5
偶数 2
单链表的第1个值是:4
单链表的第2个值是:2
奇数 l
单链表的第1个值是:1
单链表的第2个值是:3
单链表的第3个值是:5
12
感觉我的这段比书上还简单一些
代码
void deleteRepeat(LinkList &l){
LNode *p=l->next;
while(p!=NULL){
LNode *q=p->next;
//如果p->next即p为空,不做if,继续p=p->next 然后判断为空,跳出循环
if(q!=NULL && q->data==p->data){
p->next=q->next;
free(q);
}
p=p->next;
}
}
演示
LinkList l;
initList_H(l);
insertListByOrder_H(l,1,2);
insertListByOrder_H(l,2,2);
insertListByOrder_H(l,3,3);
insertListByOrder_H(l,4,3);
insertListByOrder_H(l,5,5);
//insertListByOrder_H(l,6,6);
printList_H(l);
deleteRepeat(l);
cout<<"删除重复"<<endl;
printList_H(l);
结果
单链表的第1个值是:2
单链表的第2个值是:2
单链表的第3个值是:3
单链表的第4个值是:3
单链表的第5个值是:5
删除重复
单链表的第1个值是:2
单链表的第2个值是:3
单链表的第3个值是:5
13
思想是什么???
先依次比较那个比较小,然后头插法.
比较小的那个后移指针
注意循环条件要是两个同时不到NULL
因为长度不同,或者大小的原因,可能有一个先到头了,此时把剩下的元素(最大的,并且有序)依次头插
逻辑相同
最后释放另一个没用到的头结点
注意利用源结点
代码
void combineDesc(LinkList &a,LinkList &b){
LNode *p=a->next;
LNode *q=b->next;
// LNode *qr; //q不断链
// LNode *pr; //p不断链
//优化其实因为两个不会 同时用到,只有一个就行
LNode *r=NULL;
a->next=NULL;
while(p!=NULL && q!=NULL){
if(p->data<q->data){
r=p->next;
p->next=a->next;
a->next=p;
p=r;
}else{
r=q->next;
q->next=a->next;
a->next=q;
q=r;
}
}
while(p!=NULL){
r=p->next;
p->next=a->next;
a->next=p;
p=r;
}
while(q!=NULL){
r=q->next;
q->next=a->next;
a->next=q;
q=r;
}
//别忘了这句
free(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,3);
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);
combineDesc(l,l2);
cout<<"合并"<<endl;
printList_H(l);
结果
单链表的第1个值是:2
单链表的第2个值是:2
单链表的第3个值是:3
单链表的第4个值是:3
单链表的第5个值是:5
单链表的第6个值是:6
单链表2
单链表的第1个值是:1
单链表的第2个值是:3
单链表的第3个值是:4
单链表的第4个值是:9
单链表的第5个值是:12
合并
单链表的第1个值是:12
单链表的第2个值是:9
单链表的第3个值是:6
单链表的第4个值是:5
单链表的第5个值是:4
单链表的第6个值是:3
单链表的第7个值是:3
单链表的第8个值是:3
单链表的第9个值是:2
单链表的第10个值是:2
单链表的第11个值是:1
14
不破坏结点怎么实现??怎们理解??? 也就是新生成是吧
头插法,尾插法,都行
代码
LinkList combineRepeat(LinkList &a,LinkList &b){
LNode *p=a->next;
LNode *q=b->next;
//头结点
LinkList l;
l=new LNode;
//头插法,别忘了置空
l->next=NULL;
while(p!=NULL && q!=NULL){
if(p->data<(q->data)){
p=p->next;
}
else if(p->data>q->data){
q=q->next;
}
else if(p->data==q->data){
//新结点
LNode *r=new LNode;
r->data=p->data;
p=p->next;
q=q->next;
//头插法
r->next=l->next;
l->next=r;
}
}
return l;
}
演示
LinkList l;
initList_H(l);
insertListByOrder_H(l,1,2);
insertListByOrder_H(l,2,2);
insertListByOrder_H(l,3,3);
insertListByOrder_H(l,4,3);
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);
cout<<"重复的"<<endl;
printList_H(combineRepeat(l,l2));
结果
单链表的第1个值是:2
单链表的第2个值是:2
单链表的第3个值是:3
单链表的第4个值是:3
单链表的第5个值是:5
单链表的第6个值是:6
单链表2
单链表的第1个值是:1
单链表的第2个值是:3
单链表的第3个值是:4
单链表的第4个值是:9
单链表的第5个值是:12
重复的
单链表的第1个值是:3