一.单链表习题(3)

二.2王道课后题

第三部分

15

image-20210412100829429

与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

image-20210412100846882

连续子序列是什么意思??是结点都连续相同,还是内容连续相同?

答:数据相同

连续子序列,怎么查找?

由于问的是b是a的连续子系列,从b的第一个位到最后的时候,必须全都包括在a中

可通过取消注释的代码,尝试不匹配的情况

在学习字符串的匹配后,可优化此过程

image-20210412110055356

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

image-20210412100858759

这是一个循环双链表

头尾结点怎么找?

第一个结点是头结点后面的,最后一个结点是头结点前面的

中间结点怎么找?

(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

image-20210412100909660

找到两个循环单链表的尾结点,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

image-20210412100919193

代码
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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值