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

本份代码练习册来自B站up:白话拆解数据结构


今日题目为:

(1)删除顺序表中的最小值(唯一),返回被删的值,删除的地方由最后一个元素补上

(2)删除顺序表中值重复的元素

因为要一个月刷完,每天大概要2-3题的样子。基本是按顺序刷的(除了今天)。


第一题:删除顺序表中的最小值(唯一),返回被删的值,删除的地方由最后一个元素补上

结构体定义:顺序表的后面都不再单独说了。看day1https://blog.csdn.net/m0_61522765/article/details/141350324?spm=1001.2014.3001.5502

 算法思想:
        因为最小值是唯一的,所以要先找到这个值,而这个值是min,需要比较出来才知道它是不是最小的。

        我们可以将第一个元素拷贝一份存到temp变量中,然后和第二个元素比较,如果第二个元素比temp小,就更新temp中的值,如果第二个元素比temp大,就继续往下找...直到找到表尾,最后的temp就是我们需要的最小值了,找到这个值的时候,需要记录下它的下标,因为顺序表本质上是个数组,根据数组下标很容易就能找到这个元素(随机访问),然后再执行删除操作。

    ElemType min = L.data[0];

    int pos=0;

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

    {

        if (L.data[i] <= min){

            min = L.data[i];

            pos = i;

        }

    }

    value = min;        //返回被删的值

        题目中还要求删除的地方由最后一个地方补上,其实就是将最后一个元素赋值给最小值处,再L.length-1即可。即使原来的L.data[length-1]处仍然还是表尾元素,但我们表长减了一个1,它不在我们表的范围了,里面的数据是多少我们不关心(就本题而言)!

    L.data[pos] = L.data[L.length-1];

    L.length--;

         实操一下:成功!

4c7df0dd73064ed8b78805e266a8bc8f.png

        完整代码如下:(在VScode环境下已成功运行)

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

// 删除顺序表中的最小值(唯一),返回被删的值,删除的地方由最后一个元素补上

typedef int ElemType;

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

bool Delete_Min(SqList &L,ElemType &value) {
    if(L.length == 0) return false;
    ElemType min = L.data[0];
    int pos=0;
    for(int i=1;i<L.length;i++)
    {
        if (L.data[i] <= min){
            min = L.data[i];
            pos = i;
        }
    }
    value = min;
    L.data[pos] = L.data[L.length-1];
    L.length--;
    return true;
}

int main() {
    SqList L;
    L.length = 6;
    srand(static_cast<unsigned int>(time(nullptr)));
    // 随机赋值
    for(int i =0;i<L.length;i++){
        L.data[i] = rand()%40;
    }

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

    ElemType minValue;
    if (Delete_Min(L, minValue)) {
        cout << "The minimum value is: " << minValue << endl;
        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;
}

第二题:删除顺序表中值重复的元素

        法一:比较容易想到的是先对这个表排个序,值重复的元素不就挨着了嘛。(后面想了一下,其他元素的位置全变了,这种解法应该不行。这里提供一种思路的改进:原方法不变,将sort加进del里,sort里面的L不加引用,然后得到的是排完序后且无重复值的表,将这个表与原表对比,找出不重复值的下标记录下来,放进这个新表就行了。可以自己尝试一下,这种方法应该是需要两个表)

// 不能之间写swap,因为c++标准库里有swap,会定义冲突

 void swap_elem(SqList &L, int i, int j){  

        int tmp = L.data[i];

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

        L.data[j] = tmp;

    }

void sort(SqList &L){        // 冒泡排序

        //从i=N-1倒回来调度,这是每次固定右边已经排序好的数组

        int N = L.length;

        for (int i = N - 1; i > 0; i--) {//i不能到0位置,因为下面依赖有0+1

            //然后每次从0--i来冒泡

            for (int j = 0; j < i; j++) {//不能等于i哦,因为依赖的是j+1

                if (L.data[j] > L.data[j + 1])

                swap_elem(L, j, j + 1);

            }

        }

    }

        排完序后,由于重复的元素是挨着的,但是有几个元素重复了你不知道,如果选择找到值重复的元素并删除他不大好做,需要像122333455这样的表,判断的次数就太多了。沿用昨天的代码思想,我们可以反着想,找重复的不好找,找不重复的不就行了吗!

bool del_(SqList &L){        //与昨天那两题差不多

    if(L.length==0) return false;

    int j=0;    //j的作用与昨天的一致

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

    {

        if(L.data[i]!=L.data[i+1])

           {

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

                j++;

           }

    }

    L.length = j;//同样无须修正

    return true;

}

         实操:成功!

ecc45e3df7d54bfea7d5c47f51163973.png

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

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

// 删除顺序表中值重复的元素

// 法一:比较容易想到的是对顺序表进行排序,值重复的必定连续。该方法时间复杂度取决于排序的复杂度。
// 如果采用的是快速排序,那么时间复杂度是O(nlogn);本解法用的是冒泡排序。

typedef int ElemType;

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

// 不能之间写swap,因为c++标准库里有swap,会定义冲突
 void swap_elem(SqList &L, int i, int j){  
        int tmp = L.data[i];
        L.data[i] = L.data[j];
        L.data[j] = tmp;
    }
void sort(SqList &L){
        //从i=N-1倒回来调度,这是每次固定右边已经排序好的数组
        int N = L.length;
        for (int i = N - 1; i > 0; i--) {//i不能到0位置,因为下面依赖有0+1
            //然后每次从0--i来冒泡
            for (int j = 0; j < i; j++) {//不能等于i哦,因为依赖的是j+1
                if (L.data[j] > L.data[j + 1]) 
                swap_elem(L, j, j + 1);
            }
        }
    }
bool del_(SqList &L){
    if(L.length==0) return false;
    int j=0;    //j的作用与day4一致
    for(int i=0;i<L.length;i++)
    {
        if(L.data[i]!=L.data[i+1])
           { L.data[j]=L.data[i];
           j++;}
    }
    L.length = j;//同样无须修正
    return true;
}

int main() {
    SqList L1,L2;
    L1.length =10;

    srand(static_cast<unsigned int>(time(nullptr)));
    // 随机赋值
    for(int i =0;i<L1.length;i++){
        L1.data[i] = rand()%5;   //必定能有重复值
    }
    cout << "Original list: ";
    for (int i = 0; i < L1.length; i++) {
        cout << L1.data[i] << " ";
    }
    cout << endl;
    sort(L1);
    cout << "sorted list: ";
    for (int i = 0; i < L1.length; i++) {
        cout << L1.data[i] << " ";
    }
    cout << endl;

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

    return 0;
}

解法二:暴力破解(不排序)

        也可以叫双指针法,i从表头开始遍历,j从i+1的位置开始遍历,如果L.data[i]和L.data[j]相等,就说明重复了,执行删除操作,将L.data[j]后面的元素往前移动一位,同时更新表长;如果不相等,就j继续往下找,直到找到相等的元素,如果一轮后没找到,说明这个元素是唯一的,就i更新,j又从i+1的位置找,重复这个过程直到i到达表尾!

//法二。暴力解法

bool new_list(SqList &L1)

{

    int i,j,m=0;

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

    for(i=0;i<L1.length-1;i++)

    {

        for(j=i+1;j<L1.length;){

            if(L1.data[i]==L1.data[j])

            {   // 删除当前元素

                for(int n=j;n<L1.length;n++)

                    L1.data[n]=L1.data[n+1];

                L1.length--;    //更新表长,同时循环条件也在更新

            }

            else j++;   //不删除元素时才让j递增

        }

    }

    return true;

}

证一下:成功!

 b555814b7e8346a8adea7df44810ac02.png

完整代码如下:(vscode已跑通)

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

// 删除顺序表中值重复的元素

// 法一:比较容易想到的是对顺序表进行排序,值重复的必定连续。该方法时间复杂度取决于排序的复杂度。
// 如果采用的是快速排序,那么时间复杂度是O(nlogn);本解法用的是冒泡排序。

typedef int ElemType;

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


//法二。暴力解法
bool new_list(SqList &L1)
{
    int i,j,m=0;
    // L2.data[j]=L1.data[i];
    for(i=0;i<L1.length-1;i++)
    {
        for(j=i+1;j<L1.length;){
            if(L1.data[i]==L1.data[j])
            {   // 删除当前元素
                for(int n=j;n<L1.length;n++)
                    L1.data[n]=L1.data[n+1];
                L1.length--;    //更新表长,同时循环条件也在更新
            }
            else j++;   //不删除元素时才让j递增
        }
    }
    return true;
}

int main() {
    SqList L1,L2;
    L1.length =10;
    L2.length =10;

    srand(static_cast<unsigned int>(time(nullptr)));
    // 随机赋值
    for(int i =0;i<L1.length;i++){
        L1.data[i] = rand()%5;   //必定能有重复值
    }
    cout << "Original list: ";
    for (int i = 0; i < L1.length; i++) {
        cout << L1.data[i] << " ";
    }
    cout << endl;

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

    return 0;
}

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值