数据结构代码集训DAY 1(考研、自学、期末均适用)

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


最近科研实验做的差不多了,想着学点技术,顺便温习一下数据结构!

就从群里的代码集训开始把,从Day2开始,Day1是c语言基础,就不敲了。


Day2 的题目是设计一个高效算法,将顺序表中的元素逆置

首先是结构体定义

typedef int ElemType;

struct SqList {

    ElemType data[100];

    int length;

};

        将int重命名成了ElemType,后面ElemType a就相当于int a,我觉得有没有这句都无所谓!

        顺序表结构体包括两个部分:存数据的定长数组、表长记录。顺序表长度只与length相关,length之外的数组部分全为0。

        每次初始化一个结构体变量,就要占用上图的内存,其中红色部分为我们的顺序表所需内存,但顺序表的length不能超过100!


        然后就开始解决问题了:所谓逆置,就是把12345的存储顺序换成54321而已!注意观察,3的位置是不变的,5和1调换了位置,2和4调换了位置,找到规律了。

        接下来要验证这种规律,试试一组更长的数123456789,逆序后是987654321,ok规律成立!下面就要写代码来实现它。

        从表头和表尾开始,交换元素,交换完后,就是表头的下一个元素和表尾的前一个元素交换了;由于顺序表的length已知,所以表头和表尾的下标都知道了(L.data[0]和L.data[L.length-1]),所以可以分别设置两个标志位i和j(也可以叫逻辑指针),一个标识表头,一个表尾,让L.data[i]和L.data[j]执行交换即可,交换完毕,i++,j--,就能继续执行下一轮交换了。

        然后问题又来了,对于12345的表,只需执行两次交换,对于123456789的表需要执行4次交换,所以怎么设置循环条件呢?表长为length,执行了(L.length-1)/2次,设置成i<(L.length-1)/2就可以了吗?不是,我们只考虑了单数的情况,如果是1234和12345678的表,虽然同样执行了2和4次交换,但是循环条件如果设置成(L.length-1)/2,(4-1)/2在c语言中等于1,那就会少一次交换,所以我们要多考虑一步,将i<(L.length-1)/2设置成i<=(L.length-1)/2。

        表长的单复数的循环条件还不一样,是不是显得过于复杂了呀,有没有方法可以结合起来呢?结合c语言的特性:5/2=2,我们可以将循环条件设成i<L.length/2;当表长为5的时候,执行两次循环,当表长为4的时候也执行两次循环,完美!

        理论成立,开始实操:(元素交换的操作也可以直接调用swap函数,已经被标准库封装好了)

// 算法思想:取一个中间哨兵,两边往中间交换值即可

bool reverse(SqList &L) {

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

    int value = L.length/2;

    int temp = 0;

    //int j=L.length-1;

    for (int i = 0; i < value; i++) {

       temp = L.data[i];

       L.data[i] = L.data[L.length-i-1];        // L.data[i] = L.data[j];

       L.data[L.length-i-1] = temp;        // L.data[j] = temp;

        // j--;

    }

    return true;

}//我这里没有用j,如果要用j的话,看上面的//部分

         SqList &L中的&代表引用,在c语言中是没有引用的,而c++中引入了这个概念,引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。简单来说加了这个&,你函数内如果改变了顺序表,那函数调用结束后这种改变仍然存在,不会随着函数结束作用域而消失!

        在笔试中(考研、期末、专升本中),可以直接用引用,无须担心他是c语言还是C++!

        if (L.length == 0) return false; 这是健壮性判断,空表你还逆置个毛啊!好的算法要尽可能考虑到所有非法的情况!

        一些小白同学(也包括我),老是在c和c++之间纠结,其实完全没这必要!对于考试来说,就是scanf、printf、cin、cout;malloc,free,new,delete等的区别,这里介绍一个方法,在cpp文件的开头加句:#include<cstdio>;可以实现cin和printf混着用。

        功能函数是写好了,得写个main函数造个表实践一下啊,看看写错没。

int main() {

    SqList L;

    L.length = 6;

    // 随机赋值

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

        L.data[i] = rand()%20;

    }

    printf("Original list: ");

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

        printf("%d ",L.data[i]);

    }

    printf("\n");

    if (reverse(L)) {

       printf("The new list is: ");

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

            printf("%d ",L.data[i]);

        }

    } else {

        cout << "error." << endl;

    }

    return 0;

}

 首先初始化一个顺序表L,随机赋6个值,然后打印原始表和逆置后的表:

OK,成功,再来试试奇数情况:

代码是正确的,且printf和cout是不是实现了混用!


完整代码如下,在vscode环境下已成功编译

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


// 设计一个高效算法,将顺序表中元素逆置
typedef int ElemType;

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

// 算法思想:取一个中间哨兵,两边往中间交换值即可
bool reverse(SqList &L) {
    if (L.length == 0) return false;
    int value = L.length/2;
    int temp = 0;
    for (int i = 0; i < value; i++) {
       temp = L.data[i];
       L.data[i] = L.data[L.length-i-1];
       L.data[L.length-i-1] = temp; 
    }
    return true;
}

int main() {
    SqList L;
    L.length = 6;
    // 随机赋值
    for(int i =0;i<L.length;i++){
        L.data[i] = rand()%20;
    }
    printf("Original list: ");
    for (int i = 0; i < L.length; i++) {
        printf("%d ",L.data[i]);
    }
    printf("\n");

    if (reverse(L)) {
       printf("The new list is: ");
        for (int i = 0; i < L.length; i++) {
            printf("%d ",L.data[i]);
        }
    } else {
        cout << "error." << endl;
    }

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值