数据结构学习:顺序表

数据结构基本概念

  • 数据:数据就是信息的载体,是能够输入到计算机中并能被计算机识别,存储和处理的符号集合。
  • 数据元素:数据元素是数据的基本单位,在程序中作为一个整体进行考虑和处理,有若干基本项组成。
  • 数据项:数据项就是构成数据元素的最小单位,也就是一个数据元素可以由多个数据项组成

数据的逻辑结构 

数据结构分为逻辑结构和物理结构。

逻辑结构

逻辑结构是指数据对象数据元素之间相互关系

四种逻辑结构如下,

  • 集合结构:数据元素除了同属于一个集合外,它们之间没有其他关系

  • 线性结构:数据元素之间一对一关系

  • 树形结构:数据元素之间呈现一对多关系

  • 图形结构:数据元素是多对多关系

物理结构 

物理结构是指数据的逻辑结构计算机中存储形式,也就是在计算机中的具体实现方法,因此也称为存储结构。

数据元素存储结构形式分为顺序存储链式存储

  • 顺序存储:把数据元素按照逻辑顺序存放在一片地址连续的存储单元里
  • 链式存储:把数据元素存放在任意的存储单元里,这组存储单元可以连续也可以不连续的,这些元素用地址(或者链指针)建立他们的联系

除了上述两种存储还有索引存储,散列存储,

  • 索引存储:就是在存储数据时建立一个附加的索引表,也就是建立一个目录(类似)
  • 散列存储:根据数据元素的特殊字段,也就是关键字计算元素的存放地址,然后数据元素按地址存放。

线性表 

线性表简介

线性表就是 零个或多个数据元素的有限序列,也就是包含若干个数据元素的一个线性序列。
线性表记作  L = (a_{0},.....a_{i-1},a_{i},a_{i+1} ..... a_{n-1})
L是表名,a为数据元素,n为表长,线性表可以为空表。
线性表L可用二元组形式描述,
                                                                L = (D,R)

其中D表示数据(Data),R表示关系(Relation),可以表示成如下,

其中<a_{i},a_{i+1}>叫做有序对,表示任意相邻元素之间的先后次序

a_{i}a_{i+1}的直接前驱,a_{i+1}a_{i}的直接后继

总结线性表特征:

  • 对于非空线性表,表头没有前驱元素
  • 对于非空线性表,表尾没有后继元素
  • 除此以外其他每个元素都有且仅有一个直接前驱和直接后继

线性表顺序存储 

如果将线性表L = (a_{0},.....a_{i-1},a_{i},a_{i+1} ..... a_{n-1})中的各个元素依次存储在计算机一片连续的存储空间,就是线性表的顺序存储,后续直接叫做顺序表。

顺序存储的优点:

  • 逻辑上相邻的两个元素存储位置是相邻的,对数据元素的存取或者查找方便
  • 存储密度高,存储的区域没有空位

顺序存储的缺点:

  • 对表的插入和删除等运算时间复杂度差

顺序表C语言编写

线性表顺序存储在C语言下编写的结构代码如下,

#define MAXSIZE 100
typedef int data_t;       /*data_t类型根据实际情况而定,这里为int/
typedef struct
{
    data_t data[MAXSIZE]; /*数组,存储数据元素*/
    int last;           /*线性表当前长度,也就是线性表中实际元素的数量*/
} sqlist,*sqlink;

存储结构如下,

        下面我们将编写一些顺序表相关的函数,在编写时我们一般会创建三个文件,分别是sqlist.h,sqlist.c,test.c,其中sqlist.h用于编写一些数据结构的定义和函数结构,sqlist.c用于编写函数具体实现,test.c用于测试每个函数是否正确。

这样编写可以让我们写的程序结构清晰,且容易进行软件复用。

在sqlist.h文件中,编写的程序如下,

typedef int data_t;
#define MAXSIZE 128

/*struct sqlist_t
{
    data_t data[MAXSIZE];
    int last;
};

typedef struct sqlist_t sqlist;
typedef struct sqlist_t *sqlist;
*/

/*为了方便理解,上面创建结构体并进行typedef和下面是一样的*/

/*定义线性表*/
typedef struct
{
    data_t data[MAXSIZE];/* data */
    int last;/* data */
}sqlist,*sqlink;

/*对线性表的一些操作API函数,具体作用请看C文件的部分*/

sqlink list_create();
int list_clear(sqlink L);
int list_free(sqlink L);
int list_empty(sqlink L);
int list_length(sqlink L);
int list_locate(sqlink L,data_t value);
int list_insert(sqlink L,data_t value,int pos);
int list_delete(sqlink L,int pos);
int list_merge(sqlink L1,sqlink L2);
int list_purge(sqlink L);
int list_show(sqlink L);

在sqlist.h文件中,我们编写相关函数的具体实现,以下是每个操作API函数的实现,

创建线性表

/*创建一个线性表*/
/*要创建一个线性表
1.首先给它申请内存空间
2.对线性表成员初始化
3.返回线性表地址*/
sqlink list_create()
{
    sqlink L;
    //malloc,通过malloc分配一个堆地址
    L = (sqlink)malloc(sizeof(sqlist));
    if (L == NULL)
    {
        printf("list malloc fail\n");
        return L;
    }

    //init                     //                           起始地址                填充值              填充长度
    memset(L,0,sizeof(sqlist));//memst函数的意思是 从此处的L指针的地址处开始填充,每个位置填充的值为0,填充的长度为sizeof(sqlist)
    L->last = -1; //初始化参数last

    //return
    return L;
}

简单操作函数

只要包括清空线性表,释放线性表内存,判断是否为空,计算线性表长度,显示线性表数据

/*清空数据表*/
/*
 *@ret 0--成功   -1--失败
*/
int list_clear(sqlink L)
{
    if(L == NULL)
        return -1;

    memset(L,0,sizeof(sqlist));//memst函数的意思是 从此处的L指针的地址处开始填充,每个位置填充的值为0,填充的长度为sizeof(sqlist)
    L->last = -1; //初始化参数last

    return 0;
}


/*释放申请的内存*/
int list_free(sqlink L)
{
    if(L == NULL)
        return -1;
    
    free(L);
    L = NULL;
    return 0;
}


/*判断线性表是否为空*/
/*para L:list
 *@ret 0--成功   -1--失败
*/
int list_empty(sqlink L)
{
    if(L->last == -1)
        return 1;
    else
        return 0;
    return 0;
}

/*线性表长度*/
int list_length(sqlink L)
{
    if(L == NULL)
        return -1;
    return L->last+1;
}

/*显示线性表数据*/
int list_show(sqlink L)
{
    if (L == NULL)
        return -1;
    if(L->last == -1)
    {
        printf("list is empty\n");
    }

    int i;
    for(i=0;i<=L->last;i++)
    {
        printf("%d ",L->data[i]);
    }

    puts("");/*换行*/

    return 0;
    
}

判断元素是否在线性表中

/*判断一个值是否在线性表L中*/
/*para L:list
 *@ret -1-表示值不存在  其他-表示值的位置
*/
int list_locate(sqlink L,data_t value)
{
    int i;
    for (i = 0; i <= L->last; i++)
    {
        if(L->data[i] == value)
            return i;
    }
    
    return -1;

}

线性表中插入元素

/*线性表插入元素*/
int list_insert(sqlink L,data_t value,int pos)
{
    int i;
    /*检查线性表是否满*/
    if(L->last == MAXSIZE)
    {
        printf("list is full\n");
        return -1;
    }

    /*判断线性表插入位置是否合法,pos->[0,last+1]*/
    if(pos < 0 || pos > L->last+1)
    {
        printf("pos is invalid\n");
        return -1;
    }

    /*移动元素*/
    for(i=L->last;i>=2;i--)
    {
        L->data[i+1] = L->data[i];
    }

    /*插入新值*/
    L->data[pos] = value;
    L->last++;
    return 0;
}

删除线性表中的元素

/*删除顺序表元素*/
int list_delete(sqlink L,int pos)
{
    int i;
    /*判断是否非空*/
    if(L == NULL)
    {
        printf("list is full\n");
        return -1;
    }
        
    /*判断输入的删除位置是否合法*/
    if(pos < 0 || pos >= L->last+1)
    {
        printf("pos is invalid\n");
        return -1;
    }

    /*删除元素,也就是移动元素覆盖*/
    for(i=pos+1;i<L->last;i++)
    {
        L->data[i-1] = L->data[i];
    }

    /*更新*/
    L->last--;

}

求线性表的并集

/*求线性表的并集,比如两个线性表为 L1=[1,4,7]  L2=[1 5 8] ---> L_merge = [1 4 7 5 8]*/
int list_merge(sqlink L1,sqlink L2)
{
    int i;
    int ret;
    /*判断L2中的参数是否在L1中存在*/
    for(i=0;i<=L2->last;i++)
    {
        ret = list_locate(L1,L2->data[i]);
        if(ret == -1)
        {
            if(list_insert(L1,L2->data[i],L1->last+1) == -1)
                return -1;
        }
        
    }
    return 0;

}

清除线性表重复元素

/*清除线性表的重复元素*/
int list_purge(sqlink L)
{
    int i = 1;
    int j;
    /*判断表是否空*/
    if(L->last == 0)
    {
        return 0;       
    }

    while (i <= L->last )
    {
        j = i-1;
        while(j >= 0)
        {
            if(L->data[i] == L->data[j])
            {
                list_delete(L,i);
                break;
            }
            else
            {
                j--;
            }
        }

        if(j < 0)
        {
            i++;
        }
    }
    


    
    return 0;
}

以上就是一些关于顺序表的创建等相关操作函数,建议大家可以对照代码理解以下,并且自己动手编写尝试。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值