线性表之——顺序表

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/starexplode/article/details/78854900

线性表

线性表是n个数据元素的有限序列。表中的元素是一个挨着一个放的。表中有一个开始的节点,有一个结束的节点,并且中间的每一个节点有且只有一个前驱和后继。

1. 线性表的抽象数据类型

线性表的抽象数据类型的定义如下:
Data:
线性表中的每数据对象集合{ a1,a2,...an },每个数据元素的类型均为DataType(自己定义的,可以是基本类型,也可以是复杂的类型)。其中,除了第一个元素 a1 外,每一个元素都有且只有一个直接前驱元素,除了最后一个元素 an 外都有且只有一个直接的后继元素。
Operation:
1. InitList(L); 初始化操作,构造一个空的线性表L;
1. ListLength(L); 求线性表的长度,返回线性表L中的元素个数。
1. GetElem(L,i,x); 用x返回线性表中第i个数据元素的值。
1. LocationElem(L,x); 按值查找,确定数据元素x在表中的位置。
1. ListInsert(L,i,x); 插入操作:在线性表L中第i个位置插入一个新元素x,L的长度加1。
1. ListDelete(L,i); 删除操作:删除线性表L中第i个位置的元素,L的长度减1。
1. ListEmpty(L); 判读线性表是否为空,空表返回true,非空表返回false;
1. ClearList(L); 将线性表L制空。
1. DestroyList(L); 销毁线性表
当然上面的只是最基本的操作,还有许多的其他操作,比如:排序,合并,复制等。

2. 线性表的顺序存储结构

线性表的存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。
当然对于现在的高级语言来说也就是数组了。一般来说,数组的零号位置不存储,会有其它用途。
线性表的顺序存储的描述为:

#include <stdio.h>
#define MAXSIZE 100 // 存储空间的分配
typedef int ElemType;  // 可以根据实际需要定义
typedef struct {
    ElemType data[MAXSIZE];
    int length;
}SqList;

2.1 线性表的初始化操作

在这之前有一些定义

#include <stdio.h>
#define MAXSIZE 100 // 存储空间的分配
#define TRUE 1
#define FALSE 0
#define ERROR 0
typedef int ElemType;  // 可以根据实际需要定义
typedef struct {
    ElemType data[MAXSIZE];
    int length;
}SqList;

对于初始化操作来讲是很简单的,就是顺序表中的长度制为0。

void InitList(SqList *L) {
    L->length = 0;
}

2.2 顺序表的插入

顺序表的插入指的是在第i个位置插入一个值为x的新元素,当然在插入后表的长度也就要+1了。如果是在表的最后一个添加还比较简单,但是插在表中间的某个位置是,就以为着表的后面的元素全部要移动,就像在食堂排队买饭,突然有一个人插队,假如插在了第二个位置,那么久意味着后面的人全部要后移。(所以,不提倡插队)。
插入算法的设计思路如下:
+ 如果插入的位置不合理,则返回ERROR
+ 如果线性表的长度大于登录数组长度,则返回ERROR,或者动态增加长度。当然一般是返回ERROR。
+ 从最后一个向前遍历到底i个位置,分别将他们向后移动一个位置
+ 将要插入的元素插在位置i出。
+ 表的长度+1

// 插入操作
// 插入操作
int ListInsert(SqList *L, int i, ElemType x) {
    int k;
    // 表已经满了,返回ERROR
    if (L->length == MAXSIZE) {
        return ERROR;
    }
    // 如果i不在数据元素所在的范围,返回ERROR
    // length+1的原因是可能插入的位置是表尾
    if (i < 1 || i > L->length + 1) {
        return ERROR;
    }
    // 如果不在表尾
    if (i < L->length) {
        for (k = L->length; k >= i; i++) {
            L->data[k+1] = L->data[k];
        }
    }
    L->data[i] = x;
    L->length++;
    return TRUE;
}

2.3 顺序表的删除

删除操作:就是将顺序表中的某一个元素删除掉。
删除就好比现在在食堂排队买饭,突然队伍中的某个人不想吃这个饭了,然后离开了,那么后面的人全部就得向前移动,将哪个位置补上。
删除算法的设计思路:
+ 如果删除位置不对,返回ERROR
+ 将元素取出
+ 然后从删除的位置开始到最有一个元素,分别将它们向前移动一个位置。
+ 表的长度减1

// 删除操作
int ListDelete(SqList *L, int i, ElemType *e) {
    int k;
    // 表为空,返回ERROR
    if (L->length == 0)
        return ERROR;
    if (i < 1 || i > L->length)
        return ERROR;
    *e = L->data[i];
    // 将表中i的后继元素向前移一个位置
    if (i < L->length) {
        for (k = i; k <= L->length - 1; k++)
            L->data[k] = L->data[k+1];
    }
    L->length--;
    return TRUE;
}

2.3 顺序表的查找

顺序表的查找就是遍历整个序列整个序列来对比查找。
如果没找到返回FALSE,找到了返回TRUE

int LocationElem(SqList L,ElemType x) {
    int i;
    for (i = 1; i <= L.length; i++) {
        if (L.data[i] == x)
            return TRUE;
    }
    return FALSE;
}

顺序表的其他操作可以通过可以直接或者间接的实现,比如线性表的长度,可以直接通过L.length得知。

2.4 顺序表的优缺点

缺点:插入、删除时需要进行大量的数据交换,时间复杂度高。
优点:可以直接获得到某个位置上的元素,查询时方便。

源码链接

猜你喜欢

转载自blog.csdn.net/starexplode/article/details/78854900