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

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


今日习题如下:

1)从有序顺序表中删除给定值s到t范围的元素

(2)将两个有序顺序表合并为一个新的有序顺序表,并返回这个新的顺序表


第一题

        和day2的第二题很像,就是比那题多了个有序的条件。所以可以沿用那天的思路,无序都能做,有序不是更简单。

        法一:和day2一样,将不属于这之间的元素插入到“新表”中

bool del_s_t(SqList &L,int s,int t){

    if(L.length==0||s>=t)   return false;

    int j=0;    // 记录被删除的个数

    for(int i =0;i<L.length;i++)

    {

        if(L.data[i]<s || L.data[i]>t )

        {

            L.data[j]=L.data[i];    //和day3一样的思想,j表示的是“新表”的位置

            j++;

        }

    }

    L.length = j;//无需修正位序,由于j++的关系,循环结束后会自己加1

    return true;

}

         法二:其实就是法一的改进,法一算是一个暴力解法,当s和t在表很后的位置时,会多出来很多无效的比较次数。而这个表是有序表,所以我们只需要找到第一个大于或者等于s的元素和第一个大于t的元素,标记一下这个两个元素,这俩元素中间的不就是我们要删除的值了吗?将后面的元素整体向前覆盖即可!

bool del_(SqList &L,int s,int t){

    if(L.length==0||s>=t)   return false;

    int i,j;

    for(i=0;i<L.length;i++) //找s

        if(L.data[i]>=s) break;

    for(j=0;j<L.length;j++) //找t

        if(L.data[j]>t) break;

   

    printf("%d %d",i,j);        // 记录一下找到的下标

    cout << endl;

    for(int m=j;m<L.length;m++)        // 整体前移

        L.data[i++]=L.data[j++];

    L.length=L.length-(j-i);        // 更新表长

    return true;

}

证一下:(由于表是随机赋值的,所以调用了一下sort函数来满足题目)

删除的范围是3到6:成功

再试一次:成功!

完整代码如下:(在vscode环境下成功跑通)

#include <iostream>
#include <cstdio>
#include <ctime>
#include<algorithm>
using namespace std;

// 从有序顺序表中删除给定值s到t范围的元素


typedef int ElemType;

struct SqList {
    ElemType data[100];
    int length;
};

// 法一:完全可以用day4的方法
bool del_s_t(SqList &L,int s,int t){
    if(L.length==0||s>=t)   return false;
    int j=0;    // 记录被删除的个数
    for(int i =0;i<L.length;i++)
    {
        if(L.data[i]<s || L.data[i]>t )
        {
            L.data[j]=L.data[i];    //和day3一样的思想,j表示的是“新表”的位置
            j++;
        }
    }
    L.length = j;//无需修正位序,由于j++的关系,循环结束后会自己加1
    return true;
}

// 法二:有序表的元素是排好的,只需要找到第一个大于或等于s和第一个大于t的下标即可
bool del_(SqList &L,int s,int t){
    if(L.length==0||s>=t)   return false;
    int i,j;
    for(i=0;i<L.length;i++) //找s
        if(L.data[i]>=s) break;
    for(j=0;j<L.length;j++) //找t
        if(L.data[j]>t) break;
    
    printf("%d %d",i,j);
    cout << endl;
    for(int m=j;m<L.length;m++)
        L.data[i++]=L.data[j++];

    L.length=L.length-(j-i);
    return true;
}

int main() {
    SqList L;
    L.length =15;
    srand(static_cast<unsigned int>(time(nullptr)));
    // 随机赋值
    for(int i =0;i<L.length;i++){
        L.data[i] = rand()%10;   
    }
    cout << "Original list: ";
    for (int i = 0; i < L.length; i++) {
        cout << L.data[i] << " ";
    }
    cout << endl;

    sort(L.data,L.data+L.length);
    cout << "sorted list: ";
    for (int i = 0; i < L.length; i++) {
        cout << L.data[i] << " ";
    }
    cout << endl;

    if (del_(L, 3,6)) {
        cout << "The new list is: ";
        for (int i = 0; i < L.length; i++) {
            cout << L.data[i] << " ";
        }
        cout << endl;
    } else {
        cout << "The list is empty." << endl;
    }

    return 0;
}

题二

        法一:将这两个表加进一个数组里,再用快速排序排一遍!空间复杂度O(n),时间复杂度为O(nlogn),这里的n表示两个表的总长度。

        法二:答案的做法,开辟一个新数组,循环遍历表1,表2元素,两两比较,小者存入结果表,重复元素也可放置;当一个表放完了,另一个表剩下的部分全部追加到表尾即可!

我懒得敲了,直接放答案,答案做法时间复杂度O(max(A,B)),空间复杂度是O(A+B)。

        法三:我自己的做法。时间复杂度为O(n1^2),n1为表1长度,空间复杂度为O(1)。

        先将表1扩充,就是改变它的length。然后就是插入的思想,将L2中比L1小的元素插入进去,如果L2还有剩余,就把整个L2表加到L1表后面。

 bool merge_(SqList &L1,SqList &L2)

    {

        if(L1.length==0||L2.length==0)  return false;

        int i=L1.length,j=0,temp;

        L1.length += L2.length;        // 扩充表长

        for(int m=0;m<i;m++)

        {

            if(L1.data[m]>=L2.data[j])

            {

                for(int n = 0;n<i-m;n++)        //元素后移

                {

                    L1.data[i-n] = L1.data[i-n-1];

                }

                L1.data[m]=L2.data[j];        // 插入进去

                i++;

                j++;

            }

        }

        if(j<L2.length)

        for(;j<L2.length;j++)

        L1.data[i++]=L2.data[j];

        return true;

    }

证一下:成功!

 

完整代码如下:(在vscode环境下已成功跑通)

#include <iostream>
#include <cstdio>
#include <ctime>
#include<algorithm>
using namespace std;

// 将两个有序顺序表合并为一个新的有序顺序表,并返回这个新的顺序表
typedef int ElemType;

struct SqList {
    ElemType data[100];
    int length;
};


//插入的思想,将L2中比L1小的元素插入进去,如果L2还有剩余,就把整个L2表加到L1表后面
    bool merge_(SqList &L1,SqList &L2)
    {
        if(L1.length==0||L2.length==0)  return false;
        int i=L1.length,j=0,temp;
        L1.length += L2.length;
        // for(i;i<L1.length;i++)
        //     L1.data[i]=L2.data[j++];
        for(int m=0;m<i;m++)
        {
            if(L1.data[m]>=L2.data[j])
            {
                for(int n = 0;n<i-m;n++)
                {
                    L1.data[i-n] = L1.data[i-n-1];
                }
                L1.data[m]=L2.data[j];
                i++;
                j++;
            }
        }
        if(j<L2.length)
        for(;j<L2.length;j++)
        L1.data[i++]=L2.data[j];
        return true;
    }

int main() {
    SqList L1,L2;
    L1.length =5;
    L2.length = 4;
    srand(static_cast<unsigned int>(time(nullptr)));
    // 随机赋值
    for(int i =0;i<L1.length;i++){
        L1.data[i] = rand()%10;   
    }
    
    sort(L1.data,L1.data+L1.length);
    cout << "sorted list L1: ";
    for (int i = 0; i < L1.length; i++) {
        cout << L1.data[i] << " ";
    }
    cout << endl;

    for(int i =0;i<L2.length;i++){
        L2.data[i] = rand()%10;   
    }
    // cout << "Original list L2: ";
    // for (int i = 0; i < L2.length; i++) {
    //     cout << L2.data[i] << " ";
    // }
    // cout << endl;
    sort(L2.data,L2.data+L2.length);
    cout << "sorted list L2: ";
    for (int i = 0; i < L2.length; i++) {
        cout << L2.data[i] << " ";
    }
    cout << endl;

    if (merge_(L1, L2)) {
        cout << "The new list is: ";
        for (int i = 0; i < L1.length; i++) {
            cout << L1.data[i] << " ";
        }
        cout << endl;
    } else {
        cout << "The list is empty." << endl;
    }

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值