【数据结构】--章节2.2----线性表的顺序表示和实现

线性表的练习题的博文链接~~戳这里

PS:

关于->.的区别
.表示左边是实体,提取右边的成员。一般用于结构体
->表示左边是指针,提取右边的成员

struct node{
	int x;
};

struct node *a; 

a是一个指向结点的指针。
我们要访问x的值,可以写*a.x,也可以写a->x

顺序存储结构 P22

书上P22页,给出了线性表的动态分配顺序存储结构,如下
注意:这里写了一个ElemType,这代表一个元素类型,使用的时候,你可以根据自己需要什么类型来改。

typedef struct{
    ElemType *elem;    //存储空间基址
    int lenth;    //当前线性表里面存放数据的长度
    int listsize; //线性表的容量
}SqlList;

算法2.3 初始化一个顺序表 P23

基于线性表的顺序存储结构,我们写出顺序表的第一个算法,算法2.3,初始化一个顺序表

ps:我写的代码和书上略有出入,是因为书上的是C++伪代码,而我用的C语言实现,所以有些地方会有不同
比如函数形参你会看到书上SqList &L这样写,这是C++里面的引用,而用C语言没有引用,所以改用指针代替,所以导致函数里面的写法也略有不同,这是语言的实现形式不一样,算法原理都一样,所以这些问题,就不再解释了。

/******
author:  1900
language: C
******/
#include<stdio.h>
#include<malloc.h>

#define List_Init_Size 100 //初始大小
#define List_Increase  10  //增量

typedef struct{
    int *elem;    //存储空间基址
    int lenth;    //当前线性表里面存放数据的长度
    int listsize; //线性表的容量
}SqList;

int InitList_Sq(SqList *L){
    L->elem=(int *)malloc(List_Init_Size*sizeof(int));
    if(!L->elem){
        return -1;//申请失败
    }
    L->lenth=0;
    L->listsize=List_Init_Size;
    return 1;
}
int main(){
    SqList L;      //声明一个顺序表
    InitList_Sq(&L);//初始化
    
    //将这个顺序表前十个空间,赋值为0-9,并且打印出来
    for(int i=0;i<10;i++){
        L.elem[i]=i;
        L.lenth++;
        printf("%d ",L.elem[i]);
    }
}

算法2.4 顺序表插入元素 P24

下面这个例子:
创建了一个空的顺序表,初始空间为10,向其中插入了12个元素(所以用到了申请空间),最后遍历打印!
顺序表插入元素要注意几点:
1、在第i个位置插入元素,下标是i-1
2、所插入位置后边的所有元素都要后移一位
3、要先考虑,空间够不够插入这个元素,若不够,先申请空间
4、移动元素,我用了书上的方法,用双指针移动(其实可以用下标移动的,会简单的多,不过这里为了和书上一致用指针吧。。)

/*
author:  1900
language: C

*/
#include<stdio.h>
#include<malloc.h>

#define List_Init_Size 10 //初始大小
#define List_Increase  10  //增量
int cnt=0;
typedef struct{
    int *elem;    //存储空间基址
    int lenth;    //当前线性表里面存放数据的长度
    int listsize; //线性表的容量
}SqList;

int InitList_Sq(SqList *L){
    L->elem=(int *)malloc(List_Init_Size*sizeof(int));
    if(!L->elem){
        return -1;//申请失败
    }
    L->lenth=0;
    L->listsize=List_Init_Size;
    return 1;
}
//在第i个位置前插入元素e
int ListInsert_Sq(SqList *L,int i,int e){

    if(i<1 || i>L->lenth+1) return -1; //位置不合法
    if(L->lenth>=L->listsize){
        int *newbase=(int *)realloc(L->elem,(L->listsize+List_Increase)*sizeof(int) );
        if(!newbase) return -1;
        L->elem=newbase;
        L->listsize+=List_Increase;
    }

    //用两个指针,一个指向位置i-1,用来插入元素e
    //另一个指向最后一个位置,用来移动元素

    int *q=&(L->elem[i-1]);
    for(int *p=&(L->elem[L->lenth-1]);p>=q;--p){
        *(p+1)=*p;
    }

    *q=e;  //插入元素e
    ++L->lenth;//表长+1

    return 0;
}
int main(){
    SqList L;      //声明一个顺序表
    InitList_Sq(&L);//初始化

    //刚开始为空  一个一个插入 插入12个数
    for(int i=1;i<=12;i++){
        ListInsert_Sq(&L,i,i);  
    }
    //遍历
    for(int i=0;i<12;i++){
        printf("%d ",L.elem[i]);
    }
}

算法2.5 顺序表删除元素 P25

下面这个代码,创建了一个顺序线性表,为其前10个空间赋值为0-9,然后使用算法2.5删除了第3个元素,并打印了删除后的顺序表。
在这里插入图片描述

/******
author:  1900
language: C
******/
#include<stdio.h>
#include<malloc.h>

#define List_Init_Size 100 //初始大小
#define List_Increase  10  //增量

typedef struct{
    int *elem;    //存储空间基址
    int lenth;    //当前线性表里面存放数据的长度
    int listsize; //线性表的容量
}SqList;

int InitList_Sq(SqList *L){
    L->elem=(int *)malloc(List_Init_Size*sizeof(int));
    if(!L->elem){
        return -1;//申请失败
    }
    L->lenth=0;
    L->listsize=List_Init_Size;
    return 1;
}
//在顺序表L种删除第i个元素 并且用e返回其值
int ListDelete_Sq(SqList *L,int i,int *e){
    if((i<1)||(i>L->lenth)) return -1;   //i要合法
    int *p=&(L->elem[i-1]); //指针p指向被删除元素地址
    *e=*p;
    int *q=&(L->elem[L->lenth-1]);//指针q指向被最后一个元素
    for(++p;p<=q;++p){
        *(p-1)=*p;//前移元素
    }
    --L->lenth;//表长减一
}
int main(){
    SqList L;      //声明一个顺序表
    InitList_Sq(&L);//初始化

    //将这个顺序表前十个空间,赋值为0-9,
    for(int i=0;i<10;i++){
        L.elem[i]=i;
        printf("%d ",L.elem[i]);
        L.lenth++;
    }
    printf("\n");

    int e=0;
    ListDelete_Sq(&L,3,&e);
    printf("被删除的元素值为:%d\n",e);
    printf("删除后的顺序表\n");
    for(int i=0;i<9;i++){
        printf("%d ",L.elem[i]);
    }
}

算法2.6 顺序表中查找元素 P26

这个算法,你可能觉得我写的根书上的不一样。其实,书上是用了一个函数指针,书上的算法的作用是,在线性表中查找符合条件的元素,我写的是查找值等于e的元素,所以书上的查找更广义一些,他可以查等于,也可以查大于,等等。条件就写在compare函数里,使用函数指针来传入函数。其他的原理都一样,掌握关键点就好。

//查找元素在线性表中的位序
int LocateElem_Sq(SqList *L,int e){
    int i=1;
    int *p=&(L->elem[0]);
    while(i<=L->lenth&&(*p!=e)){
        p++;
        i++;
    }
    if(i<L->lenth) return i; //返回位序
    else return 0;//没找到
}

算法2.7 顺序表的合并 P26

这个算法,注意不是简单的合并就行了,而是按照规则来合并,有点像归并排序的意思,但是比排序简单。
规则就是:给你两个非递减的顺序表,(所谓非递减,其实就是不严格的递增,就是带等于号的递增),要求你将其合并为一个顺序表,合并后的顺序表,仍然是非递减的。
我下面写的这个例子是:La顺序表:2 3 3 5 6 Lb顺序表:2 2 3 4 4 合并之后:合并后的Lc:2 2 2 3 3 3 4 4 5 6

/******
author:  1900
language: C
******/
#include<stdio.h>
#include<malloc.h>

#define List_Init_Size 100 //初始大小
#define List_Increase  10  //增量

typedef struct{
    int *elem;    //存储空间基址
    int lenth;    //当前线性表里面存放数据的长度
    int listsize; //线性表的容量
}SqList;

int InitList_Sq(SqList *L){
    L->elem=(int *)malloc(List_Init_Size*sizeof(int));
    if(!L->elem){
        return -1;//申请失败
    }
    L->lenth=0;
    L->listsize=List_Init_Size;
    return 1;
}
int MergeList_Sq(SqList *La,SqList *Lb,SqList *Lc){

    int *pa=&(La->elem[0]);  //指向头的指针
    int *pb=&(Lb->elem[0]);

    Lc->listsize=Lc->lenth=La->lenth+Lb->lenth;//初始化Lc

    int *pc=Lc->elem=(int *)malloc(Lc->listsize*sizeof(int));//给Lc分配空间
    if(*pc==NULL) return -1;//分配失败

    int *pa_last=&(La->elem[La->lenth-1]);  //指向尾的指针
    int *pb_last=&(Lb->elem[Lb->lenth-1]);

    while(pa<=pa_last &&pb<=pb_last){  //归并
        if(*pa<=*pb){
            *pc=*pa;pc++;pa++;
        }
        else{
            *pc=*pb;pc++;pb++;
        }
    }
    while(pa<=pa_last){   //插入La中剩余的
        *pc=*pa;pc++;pa++;
    }
    while(pb<=pb_last){   //插入Lb中剩余的
        *pc=*pb;pc++;pb++;
    }
    return 0;
}
int main(){
    SqList La,Lb,Lc;      //声明三个顺序表
    InitList_Sq(&La);//初始化
    InitList_Sq(&Lb);

    //La:2 3 3 5 6
    //Lb:2 2 3 4 4
    La.elem[0]=2;La.elem[1]=3;La.elem[2]=3;
    La.elem[3]=5;La.elem[4]=6;La.lenth=5;

    Lb.elem[0]=2;Lb.elem[1]=2;Lb.elem[2]=3;
    Lb.elem[3]=4;Lb.elem[4]=4;Lb.lenth=5;

    MergeList_Sq(&La,&Lb,&Lc);
    for(int i=0;i<10;i++)
    printf("%d ",Lc.elem[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1900_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值