数据结构代码集训day9(适合考研、自学、期末及专升本)

代码题均来自B站up:白话拆解数据结构


今日习题:

        (1)将两个递增的有序链表合并为一个递增的有序链表,不能有重复的元素,不能占用其他内存空间;

        (2)将带头单链表A分解为带头节点的单链表A和B,使得A表含原表中序号为奇数的元素,而B表中含有原表中序号为偶数的元素,且保持相对元素不变;

        (3)将(2)中的单链表A还是拆分成两个表,但在上述条件下,保持a表不变,b表元素逆置。


题1

        第一题和昨天第二题那道题完全一样,就是多了一个要求:不能有重复的元素,删除掉就行了。

Linklist sort_2to1list(Linklist &L1,Linklist &L2){

    Lnode *p,*q;

    p=L1->next;

    q=L2->next;

    while(q){

        Lnode *p_pre=L1;

        Lnode *q_next=q->next;

        p=L1->next;

        while(p&&p->data<q->data){  //找插入位置

            p_pre=p;

            p=p->next;

        }

        q->next=p;

        p_pre->next=q;

        q=q_next;

    }   //上面部分代码和昨天完全一致

   

    Lnode *s=L1,*t=L1->next;

    while(t){       // 找重复值

        if(s->data==t->data){

            s->next=t->next;

            free(t);

            t=s->next;

        }else{

        s=s->next;

        t=t->next;

        }

    }

    L2->next=NULL;

    return L1;

}

        我这里把值重复的单独做了删除操作,也有简便的写法。

Linklist sort_2to1list(Linklist &L1,Linklist &L2) {

    Lnode *p, *q;

    p = L1->next;

    q = L2->next;

    while(q) {

        Lnode *p_pre = L1;

        Lnode *q_next = q->next; // 保存 q 的下一个节点

        p = L1->next;

        // 找到合适的位置插入 q

        while (p && p->data < q->data) {

            p_pre = p;

            p = p->next;

        }

        // 如果在适当的位置插入 q

        if (!p || p->data != q->data) {

            q->next = p_pre->next;

            p_pre->next = q;

        } else {

            // 如果有相同的数据,直接跳过,不插入重复元素

            free(q);  // 释放 q 节点的内存

        }

        q = q_next;  // 继续处理下一个 q 节点

    }

   

    // 不需要再额外进行去重,因为插入时已经去重

    L2->next = NULL;

    return L1;

}

         实践:

        完整代码如下:

#include <iostream>
#include <cstdio>
#include <ctime>

using namespace std;

// 单链表结构体定义
typedef struct Lnode{
    int data;
    Lnode *next;
}Lnode,*Linklist;

Linklist list_insertbytail(Linklist &L){
    Lnode *s;
    int x;
    L = (Lnode*)malloc(sizeof(Lnode));
    L->next = NULL;
    Lnode *r = L;
    cin >> x;
    while(x!=9999){
        s = (Lnode*)malloc(sizeof(Lnode));
        s->data=x;
        s->next=NULL;

        r->next = s;
        r=r->next;
        cin >> x;
    }
    return L;
}

// 将两个递增的有序链表合并为一个递增的有序链表,不能有重复的元素,不能占用其他内存空间
Linklist sort_2to1list(Linklist &L1,Linklist &L2){
    Lnode *p,*q;
    p=L1->next;
    q=L2->next;
    while(q){
        Lnode *p_pre=L1;
        Lnode *q_next=q->next;
        p=L1->next;
        while(p&&p->data<q->data){  //找插入位置
            p_pre=p;
            p=p->next;
        }
        q->next=p;
        p_pre->next=q;
        q=q_next;
    }   //上面部分代码和昨天完全一致
    
    Lnode *s=L1,*t=L1->next;
    while(t){       // 找重复值
        if(s->data==t->data){
            s->next=t->next;
            free(t);
            t=s->next;
        }else{
        s=s->next;
        t=t->next;
        }
    }
    L2->next=NULL;
    return L1;
}

//另一种写法,简洁

Linklist sort_2to1list(Linklist &L1,Linklist &L2) {
    Lnode *p, *q;
    p = L1->next;
    q = L2->next;
    while(q) {
        Lnode *p_pre = L1;
        Lnode *q_next = q->next; // 保存 q 的下一个节点
        p = L1->next;
        // 找到合适的位置插入 q
        while (p && p->data < q->data) {
            p_pre = p;
            p = p->next;
        }
        // 如果在适当的位置插入 q
        if (!p || p->data != q->data) {
            q->next = p_pre->next;
            p_pre->next = q;
        } else {
            // 如果有相同的数据,直接跳过,不插入重复元素
            free(q);  // 释放 q 节点的内存
        }
        q = q_next;  // 继续处理下一个 q 节点
    }
    
    // 不需要再额外进行去重,因为插入时已经去重
    L2->next = NULL;
    return L1;
}

int main(){
    Linklist L1,L2;
    list_insertbytail(L1);
    list_insertbytail(L2);
    Lnode *p = L1->next;
    Lnode *q = L2->next;
    printf("origin listL1:");
    while (p != NULL) {
        printf("%d ",p->data);
        p = p->next;
    }
    printf("\n");
    printf("origin listL2:");
    while (q != NULL) {
        printf("%d ",q->data);
        q = q->next;
    }
    printf("\n");

    sort_2to1list(L1,L2);
    printf("new list:");

    Lnode *qs = L1->next;
    while (qs != NULL) {
        printf("%d-> ",qs->data);
        qs = qs->next;
    }
    printf("NULL");
    return 0;
}

题2

        直接带着代码看吧!

Linklist Decompose(Linklist &L){

    if(!L||!L->next)   return L;

    Linklist L2;        // 新建一个头结点

    L2 = new Lnode;

    L2->next=NULL;

    Lnode *p,*q,*r,*s;        // 定义一些工作指针

    p=L->next;

    q=p->next;

    L2->next=q;

    p->next=NULL;        // 断开,作为表1

    r=q->next;

    q->next=NULL;        // 断开,作为表2

    int i =1;        // 记录奇数还是偶数

    if(!r)   return L2;               // 

    while(r){        // r指针用来遍历还未插入的链表部分

        s=r->next;        // 每次循环更新s指针,s指针始终指向r指针的后面

        if(i%2==1){

           p->next=r;

           r->next=NULL;        // 断开它,不然两个链表会交叉着链接

           p=p->next;

        }

        else

        {

            q->next=r;

            r->next=NULL;        //  // 断开它,不然两个链表会交叉着链接

            q=q->next;

        }

        r=s;        // 更新r指针和计数器

        i++;

    }

    return L2;        // 返回表2即可,L1加了引用会保持这种改变

}

         由于是一个表变成两个带头结点的表,所以要先创建第二个表的头结点,然后初始化一些指针,如下图:

        这样的做法就是默认链表最少有两个结点,然后从第三个结点开始(第三个结点是单数开始),然后单数连L,偶数连L2

        这里展示一下连4结点的操作(奇数结点):就是if里面的语句

        演示结束,实践一下:

        看看特殊情况,就是我们定的规矩,3个结点的情况:

        代码如下:

#include <iostream>
#include <cstdio>
#include <ctime>

using namespace std;

// 单链表结构体定义
typedef struct Lnode{
    int data;
    Lnode *next;
}Lnode,*Linklist;

Linklist list_insertbytail(Linklist &L){
    Lnode *s;
    int x;
    L = (Lnode*)malloc(sizeof(Lnode));
    L->next = NULL;
    Lnode *r = L;
    cin >> x;
    while(x!=9999){
        s = (Lnode*)malloc(sizeof(Lnode));
        s->data=x;
        s->next=NULL;

        r->next = s;
        r=r->next;
        cin >> x;
    }
    return L;
}

// 将带头单链表A分解为带头节点的单链表A和B,使得A表含原表中序号为奇数的元素,而B表中含有原表中序号为偶数的元素,且保持相对元素不变
Linklist Decompose(Linklist &L){
    if(!L||!L->next)   return L;
    Linklist L2;
    L2 = new Lnode;
    L2->next=NULL;

    Lnode *p,*q,*r,*s;
    p=L->next;
    q=p->next;
    L2->next=q;
    p->next=NULL;
    r=q->next;
    q->next=NULL;
    int i =1;
    if(!r)   return L2;
    while(r){
        s=r->next;
        if(i%2==1){
           p->next=r;
           r->next=NULL;
           p=p->next;
        }
        else 
        {
            q->next=r;
            r->next=NULL;
            q=q->next;
        }
        r=s;
        i++;
    }
    return L2;
}


int main(){
    Linklist L;
    list_insertbytail(L);
    Lnode *p = L->next;
    printf("origin list:");
    while (p != NULL) {
        printf("%d ",p->data);
        p = p->next;
    }
    printf("\n");
    Lnode *q=Decompose(L);
    printf("new L1:");

    Lnode *s = L->next;
    while (s != NULL) {
        printf("%d-> ",s->data);
        s = s->next;
    }
    printf("NULL");
    printf("\n");

    printf("new list L2:");


    while (q ->next!= NULL) {
        printf("%d-> ",q->next->data);
        q = q->next;
    }
    printf("NULL");
    return 0;
}

 题3

        和题2差不多,很相似,偶数表采用头插法就行了,easy。

Linklist Decompose2(Linklist &L){

    if(!L||!L->next)   return L;

    Linklist L2;

    L2 = new Lnode;

    L2->next=NULL;

    Lnode *p,*q,*r,*s;

    p=L->next;

    q=p->next;

    L2->next=q;

    p->next=NULL;

    r=q->next;

    q->next=NULL;

    int i =1;

    if(!r)   return L2;

    while(r){

        s=r->next;

        if(i%2==1){

           p->next=r;

           r->next=NULL;

           p=p->next;

        }        // 上述都一致

        else

        {        // 头插法

            L2->next=r;

            r->next=q;

            q=r;

        }

        r=s;

        i++;

    }

    return L2;

}

        实践一下:

        看看特殊情况:三个结点

         代码如下:

#include <iostream>
#include <cstdio>
#include <ctime>

using namespace std;

// 单链表结构体定义
typedef struct Lnode{
    int data;
    Lnode *next;
}Lnode,*Linklist;

Linklist list_insertbytail(Linklist &L){
    Lnode *s;
    int x;
    L = (Lnode*)malloc(sizeof(Lnode));
    L->next = NULL;
    Lnode *r = L;
    cin >> x;
    while(x!=9999){
        s = (Lnode*)malloc(sizeof(Lnode));
        s->data=x;
        s->next=NULL;

        r->next = s;
        r=r->next;
        cin >> x;
    }
    return L;
}


// 还是拆分成两个表,a表不变,b表逆置
Linklist Decompose2(Linklist &L){
    if(!L||!L->next)   return L;
    Linklist L2;
    L2 = new Lnode;
    L2->next=NULL;

    Lnode *p,*q,*r,*s;
    p=L->next;
    q=p->next;
    L2->next=q;
    p->next=NULL;
    r=q->next;
    q->next=NULL;
    int i =1;
    if(!r)   return L2;
    while(r){
        s=r->next;
        if(i%2==1){
           p->next=r;
           r->next=NULL;
           p=p->next;
        }
        else 
        {
            L2->next=r;
            r->next=q;
            q=r;
        }
        r=s;
        i++;
    }
    return L2;
}


int main(){
    Linklist L;
    // list_insertbyhead(L);
    list_insertbytail(L);
    Lnode *p = L->next;
    printf("origin list:");
    while (p != NULL) {
        printf("%d ",p->data);
        p = p->next;
    }
    printf("\n");
    Lnode *q=Decompose2(L);
    printf("new L1:");

    Lnode *s = L->next;
    while (s != NULL) {
        printf("%d-> ",s->data);
        s = s->next;
    }
    printf("NULL");
    printf("\n");

    printf("new list L2:");


    while (q ->next!= NULL) {
        printf("%d-> ",q->next->data);
        q = q->next;
    }
    printf("NULL");
    return 0;
}

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值