一.单链表习题(1)

二.2王道课后题

第一部分

1

image-20210409170856381

相当经典的一道题

一般来说,写递归函数,第一句是递归出口

引用是给变量取别名,实际是同一个变量

q=p 是两个变量,指向同一个位置而已.

断链的问题–引用可以解决,对于作题来说,可以每次都加上引用

一般来说,没有结点的增删,可以不用引用

每次都是 x-x-x 不会断链,前面都删掉了

假如情况是 y-x-,此时通过引用,&l=l->next

再执行l=l->next 相当于

l->next=l->next->next

image-20210409164313590

image-20210409164356510

image-20210409172925080

代码(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

image-20210409170917907

image-20210409185705252

image-20210409195735378

代码
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

image-20210409170939899

头插法,或者保存到数组,再逆序输出

或者想到栈的思想,从而用递归实现

注意,调用的时候,为了不输出头结点.传l->next

image-20210409194051204

代码
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

image-20210409170949535

用一个值,存最小的

由于是单链表,没有前指针,要删除那个结点,必须还要保存最小值结点的前结点

两组指针

代码
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

image-20210409171008563

头插法

//怎么把最后一个指向空,尾指针? 直接L->NULL 然后后插
//链怎么生成? 新的指针r 保留原来链的信息,防止修改p->next,找不到原来链的信息

image-20210410102221334

代码(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

//最后头指针指向形成单链表

image-20210410105113760

代码(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

image-20210409171019965

image-20210410114212357

//扫描结点,按序插入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

image-20210409171032927

//和之前写的删除所有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

部分内容选自王道习题视频

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值