0
点赞
收藏
分享

微信扫一扫

数据结构与算法(C语言版)习题作业(1)线性表:删除顺序表中大于x的元素;使顺序表中第奇数个元素移到前面,第偶数个移动到后面;两个严格递增顺序表共同元素保存到新表

酷子腿长一米八 2022-03-25 阅读 59

网上关于数据结构c语言的代码稂莠不齐,有时候查找作业容易被不好的代码代入沟里,于是写了这个系列来提供一些参考,如果有什么错误也请大佬指正。

以下所有的程序都是经过多次修改的,函数编写方面不单单看重结果,有时候结果对,函数本身也是不规范的或是错误的

第一题.删除顺序表中大于x的元素。例如,线性表L=(3,7,1,5,9,6,4),x=5,执行算法后L变为(3,1,5,4).

思路:直接在原表上进行覆盖,节省空间

算法函数如下:只传入线性表和x,函数设计中不应传入其他无关紧要的参数,比如有些人会传入j,或者在写低效算法时,会传入另外一个线性表作为存储空间,都是不规范的,调用者使用函数时,只需要传入线性表和x即可,就跟sin()函数一样,调用者在使用时,只用传入x,而不是传入跟计算无关的值.如果那么做了,就会显得很奇怪,比如计算sin,要写一个sin(x,y,z),才能计算出来sin(x),y和z是编写函数的人自定义的,但是函数调用者并不知道,这种编写方式是错误的

下面看算法代码


//删除顺序表中大于x的元素
void ListDelete(SqList *L,int x){
    int j=0;//记录位置
    for(int i=0;i<(*L).length;i++){
        if((*L).elem[i]<=x){
            (*L).elem[j]=(*L).elem[i];
            j++;
        }
    }
    (*L).length = j;
}

调用(*L).elem动态数组,并且用j记录位置,以题目为例,循环遍历从3开始,小于x=5,将赋值到(*L).elem[j],初始j=0,就是赋值到第一个位置,j++,如果大于x,不作变动,只将小于x的值覆盖到前面

第一次循环:(3,7,1,5,9,6,4) x=5 (3<=5,3赋值到前面)  j=1:指向第二个数

第二次循环:(3,7,1,5,9,6,4) x=5 j=1:指向第二个数

第三次循环:(3,1,1,5,9,6,4) x=5 (1<=5,1赋值到前面) j=2:指向第三个数

第四次循环:(3,1,5,5,9,6,4) x=5 (5<=5,5赋值到前面) j=3:指向第四个数

第五次循环:(3,1,5,5,9,6,4) x=5 

第六次循环:(3,1,5,5,9,6,4) x=5

第七次循环:(3,1,5,4,9,6,4) x=5  (4<5,4赋值到j的位置)

循环结束,(*L).length忠实的记录顺序表的长度,此时为4(实际上不为4,因为后面的空间未删除,但是当你设定它为4的时候,以后的操作都相当于长度为4了)

完整代码如下

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

const int ListInitSize = 100;  //线性表初始存储空间
const int ListInc = 10;    //线性表存储空间的分配增量

typedef struct{
    int *elem;      //存储线性表元素的动态数组
    int length,listsize; //表的长度与当前分配的存储容量
} SqList;

//顺序表初始化操作,存入若干数据
bool ListInit(SqList *L,int n,int a[]);
//删除顺序表中大于x的元素
void ListDelete(SqList *L,int x);

int main(){
    SqList L;
    int n=7,a[7]={3,7,1,5,9,6,4},x=5;
    ListInit(&L,n,a);
    ListDelete(&L,x);
    printf("线性表L =(");
    for(int i=0;i<L.length;i++){
        printf("%d ",L.elem[i]);
    }
    printf(")");
}

//顺序表初始化操作,存入若干元素
bool ListInit(SqList *L,int n,int a[]){
    (*L).elem =(int*)malloc((ListInitSize+n)*sizeof(int));//分配内存
    if(!(*L).elem){//分配内存失败
        return false;
    }
    (*L).length = n;
    (*L).listsize = n+ListInitSize;
    for(int i=0;i<n;i++){
        (*L).elem[i]=a[i];
    }
}

//删除顺序表中大于x的元素
void ListDelete(SqList *L,int x){
    int j=0;
    for(int i=0;i<(*L).length;i++){
        if((*L).elem[i]<=x){
            (*L).elem[j]=(*L).elem[i];
            j++;
        }
    }
    (*L).length = j;
}

第二题.改变顺序表的元素次序,第奇数个元素移到前面,第偶数个元素移到后面.例,线性表L=(1,2,3,4,5,6,7)变为(1,3,5,7,2,4,6).

思路:对原有顺序表的排序,并存储到新的动态数组上,最后将数组整个赋值给原有顺序表,这样的时间复杂度只有一重循环了,如果考虑节省空间,也可以将原有动态数组删除.

动态数组的赋值实际上是将地址传过去了,不需要再开一个循环去赋值

算法代码如下:缺点如下:n的取整不用这么麻烦,有更简单的,而且受惯性思维影响,写代码时人为分了奇偶,不用分奇偶两种情况也可以赋值,读者可以自行思考

//奇数项移到前面,偶数项移到后面
bool ListMove(SqList *L){
    int *A;//一个新的动态数组
    A =(int*)malloc(((*L).listsize)*sizeof(int));//动态数组分配内存
    if(!A){//分配内存失败
        return false;
    }
    int n=(int)ceil(((double)(*L).length)/2);//除以2并向上取整
    if((*L).length%2==0){//判断如果顺序表有偶数个元素
        for(int i=0;i<n;i++){
            A[i+n]=(*L).elem[2*i+1];//偶数项插入
            A[i]=(*L).elem[2*i];//奇数项插入
        }
    }
    else{//判断如果顺序表有奇数数个元素
        A[0]=(*L).elem[0];
        for(int i=1;i<n;i++){
            A[i+n-1]=(*L).elem[2*i-1];//偶数项插入
            A[i]=(*L).elem[2*i];//奇数项插入
        }
    }
    (*L).elem = A;//直接赋值地址
    return true;
}

完整代码如下

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <math.h>

const int ListInitSize = 100;  //线性表初始存储空间
const int ListInc = 10;    //线性表存储空间的分配增量

typedef struct{
    int *elem;      //存储线性表元素的动态数组
    int length,listsize; //表的长度与当前分配的存储容量
} SqList;

//顺序表初始化操作,存入若干数据
bool ListInit(SqList *L,int n,int a[]);
//奇数项移到前面,偶数项移到后面
bool ListMove(SqList *L);

int main(){
    SqList L;
    int n=21,a[21]={1,2,3,4,5,6,7,8,10,12,14,16,18,20,23,26,29,33,37,41,44};

    ListInit(&L,n,a);
    ListMove(&L);
    printf("线性表L =(");
    for(int i=0;i<L.length;i++){
        printf("%d ",L.elem[i]);
    }
    printf(")");
}

//顺序表初始化操作,存入若干元素
bool ListInit(SqList *L,int n,int a[]){
    (*L).elem =(int*)malloc((ListInitSize+n)*sizeof(int));//分配内存
    if(!(*L).elem){//分配内存失败
        return false;
    }
    (*L).length = n;
    (*L).listsize = n+ListInitSize;
    
    for(int i=0;i<n;i++){
        (*L).elem[i]=a[i];
    }
    return true;
}

//奇数项移到前面,偶数项移到后面
bool ListMove(SqList *L){
    int *A;
    A =(int*)malloc(((*L).listsize)*sizeof(int));//动态数组分配内存
    if(!A){//分配内存失败
        return false;
    }
    int n=(int)ceil(((double)(*L).length)/2);//除以2并向上取整
    if((*L).length%2==0){
        for(int i=0;i<n;i++){
            A[i+n]=(*L).elem[2*i+1];//偶数项插入
            A[i]=(*L).elem[2*i];//奇数项插入
        }
    }
    else{
        A[0]=(*L).elem[0];
        for(int i=1;i<n;i++){
            A[i+n-1]=(*L).elem[2*i-1];//偶数项插入
            A[i]=(*L).elem[2*i];//奇数项插入
        }
    }
    (*L).elem = A;
    return true;
}

持续更新中......

举报

相关推荐

0 条评论