数据结构-2顺序表

线性表

具有唯一前驱和唯一后继的数据结构(头节点、尾节点例外)就是线性表

根据存储结构:

1.顺序表:在内存中连续存储(定义数组、malloc实现)

1.有空和满的状态
2.增加、删除的算法比较麻烦
3.修改和查询算法比较方便

2.链表: 在内存中随机存储不连续的链式结构(malloc开辟每一个节点,并将节点连在一起(将前一个节点里面的指针指向后一个节点))

1.有空的状态(只有头节点即空)但没有满的状态
2.链表增加或者删除比较简单
3.链表数据的查询和修改比较麻烦

顺序表

#include <stdio.h>
int main()
{
    int arr[10]={0},tail=-1; //arr可以看作是一个顺序表,tail记录表中有效数据的个数
    arr[++tail]=1;            //向表中插入数据
    arr[++tail]=2;
    arr[++tail]=3;
    arr[++tail]=4;            //这样设计很不合理,因为很容易破坏表的结构,如下代码
    //tail=-1;   //就把表的结构破坏掉了
    for(int i=0;i<=tail;i++)
    printf("%d",arr[i]);
    puts("");    
}
    //且arr[]和tail没有关联性

顺序表较好的实现:

#include <stdio.h>
typedef struct data        //声明一个结构体,来表示顺序表
{
    int arr[100];
    int tail;
}Data;
                //p:插入的表地址    pos:插入的位置    data:插入的数据
                //返回值 : 0 成功  -1失败
int insert_data(Data *p,int pose,int data)
{
    if(pos<0||pos>p->tail||pos==100||NULL==p)
    {
        puts("arg err");        //    插入失败的错误显示
        return -1;    
    }
    
    for(int i=p->tail;i>pos;i--)
    {
        p->arr[i]=p->arr[i-1];    //后移算法,将pos后的所有数据后移一位
    }
    
    p->arr[pos]=data;            //将插入的数据放到对应位置
    p->tail++;                    //插入新数据,有效数据+1
    return 0;
}
void show(Data *p)            //一个显示函数
{
    for(int i=0;i<p->tail;i++)
    printf("%d",p->arr[i]);
    puts("");
}
int main()
{
    Data list={0};             //定义了一个具体的顺序表(定义了一个结构体变量)
    int data;
    for(int i=0;i<10;i++)
    {
        printf("please input %d num\n",i);
        scanf("%d",&data);
        insert_data(&list,i,data)    
    }
    show(&list);
    return 0;
}

顺序表最好的实现(将表存在堆区):

list.h

#ifndef _LIST_H
#define _LIST_H
#include <stdio.h>
typedef struct data{        //声明一个结构体类型,来表示顺序表
    int *arr;               //到时会用其指向一个malloc新开辟的空间,用于储存数组
    int tail;
    int len;
}Data,*Pdata;

//Pdata init(int len);        //初始化函数:创建一个顺序表对象
int init(Pdata *p,int len);

int insert_data(Pdata L,int poss,int data);    
int delete_data(Pdata L,int pos);
int change_data(Pdata L,int pos,int data);
int select_data(Pdata L,int pos);

int empty(Pdata L);        //判断该数组是否为空
int full(Pdata L);         //判断该数组是否已满
void show(Pdata L);

#endif

list.c

#include "list.h"
#include <stdio.h>
/*
typedef struct data{        // list.h声明了,list.c不用重新声明,放在这里便于分析
    int *arr;               //malloc开辟一个堆区空间,要用arr指向
    int tail;
    int len;
}Data,*Pdata;
*/
/*Pdata init(int len)                //初始化函数,将结构体初始化
{
    Pdata p=malloc(sizeof(Data));  //开辟一个堆区空间,储存结构体,即一个指针,两个int变量
    if(NULL==p)            //判断是否开辟成功        
    {
        perror("malloc");// puts("malloc err");    
        return NULL;
    }
    p->arr=malloc(sizeof(int)*len);    //在堆区再开辟一个空间给结构体的arr,用于存储顺序表
    if(NULL==p->arr)                   //是否开辟成功
    {
        free(p);                    //为什么前面不释放?
        perror("malloc");
        return NULL;    
    }
    p->tail=0;            //初始化,数据都为0
    p->len=len;           //开辟多少长度的空间,长度需有值,传参进来的
    return p;    
}*/
int init(Pdata *p,int len)  //效果同上,通过二级指针来使实参(地址)改变,
{                           //此时*p就是实际参数,就不用返回地址在主函数里接受了
    *p=malloc(sizeof(Data));
     if(NULL == *P)
    {
        perror("malloc");
        return -1;
    }
     (*P)->arr = malloc(sizeof(int)*len);
    if(NULL == (*P)->arr)
    {
        perror("malloc");
        free(*P);
        return -1;
    }
    (*P)->tail = 0;
    (*P)->len = len;
    
    return 0;
}

int insert_data(Pdata L,int pos,int data)
{
    if(NULL==L)
        return -1;        //指针传参失败
    if(full(L))
        return -1;        //顺序表满了
    if(pos<0||pos>L->tail)
        return -1;        //其他导致执行错误的情况
        
    for(int i=L->tail;i>pos;i--)
        L->arr[i]=L->arr[i-1];
    p->arr[pos]=data;
    p->tail++;
    
    return 0;
}

int delete_data(Pdata L,int pos)
{
    if(NULL == L || empty(L) || pos < 0 || pos >= L->tail)
    {
        puts("delete arg err");
        return -1;
    }

    int data = L->arr[pos]; //记录被删除的元素
    for(int i = pos; i < L->tail; i++)
        L->arr[i] = L->arr[i+1];
    L->tail--;  //已经删除了一个数据,所以有效元素的个数需要-1
    return data;
}

int change_data(Pdata L,int pos,int data)
{
    if(NULL == L || pos < 0 || empty(L) || pos >= L->tail)
    {
        puts("arg err");
        return -1;
    }    
    L->arr[pos] = data;  //更改数据
    return 0;
}
int select_data(Pdata L,int pos)
{
    if(NULL == L || empty(L) || pos < 0 || pos >= L->tail){
        puts("select err");
        return -1;
    }
        //int data = L->arr[pos];
        //return data;   
    return L->arr[pos];    //返回被删除的值
}


int empty(Pdata L)
{
    if(NULL==L)        //传参失败,L未指向结构体
        return 0;
    if(0==L->tail)      //空的
        return 1;
    else
        return 0;
}
int full(Pdata L)
{
    if(NULL==L)
        return 0;
    if(L->len==L->tail)    //满的
        return 1;
    else
        return 0;
}
void show(Pdata L)
{
    if(NULL==L||empty(L))
        return;
    for(int i=0;i<L->tail;i++)
        printf("%d",L->arr[i]);
    puts("");
    
}

mian.c

#include <stdio.h>
#include "list.h"
int mian()
{
    int data,num,ret,pos=0;
xxx:
    puts("please input list num");
    scanf("%d",&num);
    if(0>num)
    {
        puts("input err");
        goto xxx;    
    }
    
    Pdata p=NULL;
    init(&p,num);
    
       //表里没有数据,通过插入数据的方式从头输入数据,直到输入非数字数据退出
    while(1){        
        printf("please input data:");    
        ret=scanf("%d",&data);    
        //printf("ret =%d\n",ret);//ret是scanf的返回值EOF,查看是否输入成功。
                                    // 调试信息
        if(0==ret)  // 输入正确EOF==1      
            break;    //返回值为0,即输入失败了,输入到非数字数据退出循环,不再输入
    insert_data(p,pos,data)   //确认是数字字符,就往表里挨个插入
    pos++;        //也可以insert_data(p,pos++,data)
    }
    getchar();//吃掉退出时的输入字符
    
    show(p);
    printf("please input delete data--->pos: ");
    scanf("%d", &pos);
    printf("%d deleted!\n", delete_data(p, pos));
    show(p);
    
    return 0;        
}

自己写的程序   DS->day2里

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值