文章目录
二.2王道课后题
第一部分
1
相当经典的一道题
一般来说,写递归函数,第一句是递归出口
引用是给变量取别名,实际是同一个变量
q=p 是两个变量,指向同一个位置而已.
断链的问题–引用可以解决,对于作题来说,可以每次都加上引用
一般来说,没有结点的增删,可以不用引用
每次都是 x-x-x 不会断链,前面都删掉了
假如情况是 y-x-,此时通过引用,&l=l->next
再执行l=l->next 相当于
l->next=l->next->next
代码(1)推荐
void del_x_recursion(LinkList &l,int x){
if(l==NULL){ //递归出口
return;
}
if(l->data!=x){
del_x_recursion(l->next,x);
return; //递归出口 层层返回
}
LNode *p=l; //删除结点p
l=l->next;
free(p);
del_x_recursion(l,x);
}
演示
LinkList l;
initList(l);
cout<<"正常插入 1"<<endl;
int i=1;
insertListByOrder(l, 1,i);
insertListByOrder(l, 2,3);
insertListByOrder(l, 3,i);
printList(l);
//del_x(l,1);
del_x_recursion(l,1);
cout<<"删除 1后"<<endl;
printList(l);
结果
正常插入 1
单链表的第1个值是:1
单链表的第2个值是:3
单链表的第3个值是:1
删除 1后
单链表的第1个值是:3
代码(2)
用的偷天换日之计,其实不必
void del_x(LinkList &l,int x){
if(l==NULL){ //终止条件
return;
}
if(l->data==x){ //删除结点
LNode *p=l->next;
//小心空指针
if(p==NULL){
l=NULL;
return;
}
l->data=p->data;
l->next=p->next;
free(p);
//继续调用
del_x(l,x);
}
if(l!=NULL){
del_x(l->next,x);
}
}
2
代码
void del_x_H(LinkList &l,int x){
LNode *pre=l;
LNode *p=l->next;
while(p!=NULL){
if(p->data!=x){
pre=p;
p=p->next;
}
else{
LNode *q=p;
p=p->next;
pre->next=p;
free(q);
}
}
}
演示
LinkList l;
initList_H(l);
int i=1;
insertListByOrder_H(l,1,i);
insertListByOrder_H(l,2,2);
insertListByOrder_H(l,3,i);
printList_H(l);
del_x_H(l,1);
cout<<"删除 1后"<<endl;
printList_H(l);
结果
单链表的第1个值是:1
单链表的第2个值是:2
单链表的第3个值是:1
删除 1后
单链表的第1个值是:2
代码(2)
尾插法
void del_x_H_02(LinkList &l,int x){
LNode *p=l->next;
LNode *r=l; //尾结点,初始为头结点
while(p!=NULL){
if(p->data==x){ //释放这个结点
LNode *q=p;
p=p->next;
free(q);
//肯定不会要这句,下一个还不确定值呢
//r->next=p;
}
else{
r->next=p;
r=p;
p=p->next;
}
}
r->next=NULL; //最后尾结点指向空
}
演示
单链表的第1个值是:1
单链表的第2个值是:2
单链表的第3个值是:1
删除 1后
单链表的第1个值是:2
结果
单链表的第1个值是:1
单链表的第2个值是:2
单链表的第3个值是:1
删除 1后
单链表的第1个值是:2
3
头插法,或者保存到数组,再逆序输出
或者想到栈的思想,从而用递归实现
注意,调用的时候,为了不输出头结点.传l->next
代码
void reprint02(LinkList &l){
//LNode *p=l->next;
//while(p!=NULL){
if(l->next!=NULL){
reprint02(l->next);
}
cout<<l->data<<endl;
}
演示
LinkList l;
initList_H(l);
insertListByOrder_H(l,1,1);
insertListByOrder_H(l,2,2);
insertListByOrder_H(l,3,3);
printList_H(l);
//reprint(l);
reprint02(l->next);//跳过头结点
结果
单链表的第1个值是:1
单链表的第2个值是:2
单链表的第3个值是:3
3
2
1
4
用一个值,存最小的
由于是单链表,没有前指针,要删除那个结点,必须还要保存最小值结点的前结点
两组指针
代码
void delMin(LinkList &l){
LNode *pre=l;
LNode *p=l->next;
LNode *minpre=pre;
LNode *min_p=p;
while(p!=NULL){ //遍历查找最小
if(p->data<min_p->data){
min_p=p;
minpre=pre;
}
pre=p; //指针跳到下一个结点
p=p->next;
}
minpre->next=min_p->next;
free(min_p);
//删除结点
}
演示
LinkList l;
initList_H(l);
insertListByOrder_H(l,1,5);
insertListByOrder_H(l,2,2);
insertListByOrder_H(l,3,1);
insertListByOrder_H(l,3,3);
insertListByOrder_H(l,3,4);
printList_H(l);
delMin(l);
cout<<"删除最小的后"<<endl;
printList_H(l);
结果
单链表的第1个值是:5
单链表的第2个值是:2
单链表的第3个值是:4
单链表的第4个值是:3
单链表的第5个值是:1
删除最小的后
单链表的第1个值是:5
单链表的第2个值是:2
单链表的第3个值是:4
单链表的第4个值是:3
5
头插法
//怎么把最后一个指向空,尾指针? 直接L->NULL 然后后插
//链怎么生成? 新的指针r 保留原来链的信息,防止修改p->next,找不到原来链的信息
代码(1)
void reverse01(LinkList &l){
LNode *p=l->next;
LNode *r;
l->next=NULL;
while(p!=NULL){
r=p->next; //先保留原来链的信息
p->next=l->next;
l->next=p;
p=r;
}
}
//指针反转
//由于翻转,所以需要保留前驱结点
//为了不断链,需要保存后继结点
//第一个结点是尾结点->NULL
//最后头指针指向形成单链表
代码(2)
void reverse02(LinkList &l){
LNode *p=l->next;
LNode *r=p->next; //后继
LNode *pre; //前结点
p->next=NULL;
while(r!=NULL){ //循环到p指向了最后一个结点
pre=p;
p=r;
r=r->next;
p->next=pre;
}
l->next=p;
}
演示
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);
// reverse01(l);
reverse02(l);
cout<<"逆置"<<endl;
printList_H(l);
结果
单链表的第1个值是:1
单链表的第2个值是:2
单链表的第3个值是:3
单链表的第4个值是:4
单链表的第5个值是:5
逆置
单链表的第1个值是:5
单链表的第2个值是:4
单链表的第3个值是:3
单链表的第4个值是:2
单链表的第5个值是:1
6
//扫描结点,按序插入o(n*n)
//不断链,需要后继指针r
//因为插入,需要知道前驱结点的信息,
//另外需要遍历已经有序的部分,设计pre指针
//判断条件1遇到插入的数小于pre->next,就放在pre的后面
//判断条件2,pre已经走到头了,即此时插入的数据最大,就直接放在最后
代码
void sortUp(LinkList &l){
LNode *p=l->next;
LNode *r=p->next;
LNode *pre;
p->next=NULL;
p=r;
while(p!=NULL){ //p一直指向无序部分的第一个,为空就表示结束
r=p->next; //不断链
pre=l; //有序的部分开始遍历
while(pre->next!=NULL&&pre->next->data<p->data){//查找插入的位置
pre=pre->next;
}
//插入
p->next=pre->next;
pre->next=p;
p=r;
}
}
演示
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);
sortUp(l);
cout<<"逆置"<<endl;
printList_H(l);
结果
单链表的第1个值是:1
单链表的第2个值是:4
单链表的第3个值是:3
单链表的第4个值是:2
单链表的第5个值是:5
逆置
单链表的第1个值是:1
单链表的第2个值是:2
单链表的第3个值是:3
单链表的第4个值是:4
单链表的第5个值是:5
7
//和之前写的删除所有x的值很像
//注意删除要保留前面的结点信息所以设计pre指针
代码
void del_Betwen(LinkList &l,int x,int y){
LNode *p=l->next;
LNode *pre=l;
while(p!=NULL){
if(p->data>=x&&p->data<=y){
LNode *q=p;
pre->next=p->next;
p=p->next; //下面这两行也可以改成//free(q) p=pre->next
free(q);
}else{
pre=p;
p=p->next;
}
}
}
演示
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);
del_Betwen(l,2,4);
cout<<"逆置"<<endl;
printList_H(l);
结果
单链表的第1个值是:1
单链表的第2个值是:4
单链表的第3个值是:3
单链表的第4个值是:2
单链表的第5个值是:5
逆置
单链表的第1个值是:1
单链表的第2个值是:5
部分内容选自王道习题视频