数据结构与算法-第1章 线性表-1.1顺序表

107 阅读9分钟

什么是线性表,线性表的特性是什么?(1)线性表是具有相同数据类型的元素组成的一个有限序列。有限指的是线性表中元素个数是有限的。线性表中元素的个数等于线性表的长度。当线性表中没有元素时,说明线性表为空。(2)线性表中有1个表头元素,有1个表尾元素,除表头与表尾元素之外,线性表中每1个元素只有1个前驱元素,每1个元素只有1个后继元素。线性表中的表头元素没有前驱,表尾元素没有后继。(3)线性表按照存储方式分为顺序表和链表,用数组存储的线性表叫做顺序表,用链表存储的线性表叫做链表。(4)线性表中元素可以是有序的,也可以是无序的。(5)顺序表中元素的下标等于元素的位置-1。如图1.1.1所示是一个用数组存储的线性表和1个用链表存储的线性表。

1.1.1.png

图1.1.1

1.1 顺序表

1.1.1 顺序表的定义、创建与遍历

定义1个结构体用来表示顺序表,结构体成员有1个数组,这个数组用来存储顺序表中的元素,有1个int类型的变量length用来表示顺序表的长度。 顺序表的结构体定义代码如下:

#include<stdio.h>
//定义常量MaxSize用来记录顺序表中最多可以存放元素的个数
#define MaxSize 10
//定义顺序表
typedef struct SqList{
    //数组R用来存储顺序表中的元素
    int R[MaxSize];
    //顺序表的表长,也就是顺序表中实际存储元素的个数
    int length;
}SqList; 

声明1个顺序表之后一定要对顺序表进行初始化,顺序表初始化代码如下:

//顺序表初始化
void InitSqList(SqList &L){
    //将顺序表中元素个数设置为0
    L.length = 0;
}

顺序表的创建代码如下:

int main(){
    //声明1个顺序表L
    SqList L;
    //顺序表初始化
    InitSqList(L);
    int data[5] = {10,20,30,60,80};
    //在顺序表L中插入元素
    for(int i=0;i<=4;i++){
        L.R[i] = data[i];
        //顺序表表长+1
        L.length++;
    }
    return 0;
}

顺序表的遍历与数组的遍历类似。顺序表的遍历代码如下:

void SqListTraverse(SqList L){
    for(int i=0;i<=L.length-1;i++){
        printf("%d ",L.R[i]);
    }
}

1.1.2 顺序表的按位置查找元素的值

什么是顺序表的按位置查找元素?位置从1开始递增。下标从0开始递增。元素的位置=元素的下标+1。元素的下标=元素的位置-1。 顺序表的按位置查找其实就是通过下标访问到某个元素。元素的位置 i 的取值范围是[1 , 顺序表元素的个数],顺序表的按位置查找元素代码如下:

//顺序表的按位置查找,查找第i个位置元素的值
int SqListByLocationSelect(SqList L,int i){
    //判断i的值是否正确
    if(i<1||i>L.length){
        return -1;
    }
    //元素的下标=元素的位置-1
    //查找第i个元素,就是查找下标为i-1的元素
    return L.R[i-1];
}

1.1.3 顺序表的按值查找元素的位置

什么是顺序表的按值查找位置?这里的值指的是顺序表中元素的值key,根据顺序表中元素的值找到这个元素在顺序表中的位置,注意这里是元素的位置不是元素的下标。顺序表的按值查找位置,需要遍历顺序表,顺序表的遍历方法和数组相同。找到了key之后,返回key在顺序表中的位置。没有找到key,说明key在顺序表中不存在,返回-1,顺序表的按值查找代码如下:

//顺序表的按值查找,查找key在顺序表中的位置
int SqListByValueSelect(SqList L,int key){
    //遍历顺序表
    for(int i=0;i<L.length;i++){
        //如果找到了key
        if(L.R[i]==key){
            //i是key的下标,转换成位置就是i+1
            return i+1;
        }
    }
    //执行到这里说明key不存在
    return -1;
}

1.1.4 顺序表的按位置插入元素

在顺序表中第i个位置插入元素key,需要判断插入位置i是否正确,插入位置i 的取值范围是[1 , 顺序表元素个数+1],还需要判断顺序表是否已满,如果顺序表中元素的个数大于或者等于顺序表的最大容量,则说明顺序表已满不能插入新元素。插入完成之后顺序表元素个数加1,顺序表的按位置插入元素具体过程如图1.1.2所示:

1.1.2.png

图1.1.2

如果在顺序表中最后1个元素后面插入元素,则不需要移动任何元素。

顺序表中按位置插入元素代码如下:

//在顺序表中第i个位置插入元素key
bool SqListByLocationInsert(SqList &L,int key,int i){
    //判断插入的位置i是否正确
    if(i<1||i>L.length+1){
        return false;
    }
    //判断顺序表是否已满
    if(L.length>=MaxSize){
        return false;
    }
    //如果在顺序表中最后1个元素后面插入元素,则不需要移动任何元素。
    //如果插入位置i等于顺序表元素个数+1说明是在顺序表最后1个元素后面插入元素
    if(i==L.length+1){
        //在下标i-1处插入元素key
        L.R[i-1] = key;
        return true;
    }
    //将下标[i-1,length-1]的元素从后往前依次向后移动1个位置
    //j是当前需要移动的元素的下标,j的值是递减的
    //从最后一个元素开始移动,所以j的初始值等于最后一个元素的下标
    //j的最小值为i-1
    for(int j=L.length-1;j>=i-1;j--){
        //将下标j指向的元素向后移动1位,移动到j+1处
        L.R[j+1] = L.R[j];
    }
    //在下标i-1处插入key
    L.R[i-1] = key;
    L.length++;
    return true;
}

1.1.5 在顺序表指定元素的前面或后面插入元素

在顺序表指定元素的前面或后面插入元素,需要先查找这个指定元素在顺序表中的位置。查找指定元素在顺序表中的位置参见1.1.3小节。如果指定元素在顺序表中的位置是 i,在指定元素的前面插入元素就是在第 i 个位置插入元素。在指定元素的后面插入元素就是在第 i +1个位置插入元素。具体过程如图1.1.3所示:

1.1.3.png

图1.1.3

在顺序表指定元素的前面插入元素的代码如下:

//value是指定元素,key是插入元素的值
bool SqListElemFrontInsert(SqList &L,int value,int key){
    //查找指定元素value在顺序表中的位置i
    int i = SqListByValueSelect(L,value);
    //如果i等于-1说明指定元素value不存在
    if(i==-1){
        return false;
    }
    //在指定元素的前面插入元素就是在顺序表第i个位置插入元素key
    SqListByLocationInsert(L,key,i);
    return true;
}

在顺序表指定元素的后面插入元素的代码如下:

//value是指定元素,key是插入元素的值
bool SqListElemBehindInsert(SqList &L,int value,int key){
    //查找指定元素value在顺序表中的位置i
    int i = SqListByValueSelect(L,value);
    //如果i等于-1说明指定元素value不存在
    if(i==-1){
        return false;
    }
    //在指定元素的后面插入元素就是在顺序表第i +1个位置插入元素key
    SqListByLocationInsert(L,key,i+1);
    return true;
}

1.1.6 顺序表的按位置删除元素

在顺序表中第i个位置删除元素key,需要判断位置 i 是否正确,i 的取值范围是[1 , 顺序表元素的个数],还需要判断顺序表是否为空,如果顺序表为空则不能删除元素。删除完成之后顺序表元素个数减1,删除第 i 个位置的元素就是删除下标为 i -1的元素。顺序表的按位置删除元素具体过程如图1.1.4所示:

1.1.4.png

图1.1.4

顺序表中按位置删除元素代码如下:

//删除顺序表L中第i个位置的元素
bool SqListByLocationDelete(SqList &L,int i){
    //判断删除的位置是否正确
    if(i<1||i>L.length){
        return false;
    }
    //判断顺序表是否为空
    if(L.length == 0){
        return false;
    }
    //将下标[i,length-1]的元素从前往后依次向前移动1个位置
    //j是当前需要移动的元素的下标,j的值是递增的
    //从要删除的元素的后一个元素开始移动,所以j的初始值等于i
    //j的最大值为L.length-1
    for(int j=i;j<=L.length-1;j++){
        //将下标j指向的元素向前移动1位,移动到j-1处
        L.R[j-1] = L.R[j];
    }
    L.length--; 
    return true;
}

1.1.7 顺序表的按值删除元素

顺序表的按值删除指的是根据元素的值删除元素, 顺序表的按值删除需要先查找元素在顺序表中的位置。顺序表的按值查找元素的位置参见1.1.3小节。找到元素的位置之后,顺序表的按值删除就转变成顺序表的按位置删除元素。顺序表的按位置删除元素参见1.1.6小节。顺序表的按值删除代码如下:

//顺序表的按值删除元素
bool SqListByValueDelete(SqList &L,int key){
    //查找删除元素key在顺序表中的位置i
    int i = SqListByValueSelect(L,key);
    //如果i等于-1说明删除元素key不存在
    if(i==-1){
        return false;
    }
    //删除第i个位置的元素
    SqListByLocationDelete(L,i,e);
    return true;
}

1.1.8 顺序表的按位置修改元素

顺序表的按位置修改指的是修改顺序表中第i个位置的元素,i 的取值范围是[1 , 顺序表中元素的个数],元素的下标等于元素的位置-1,顺序表的按位置修改代码如下:

//将顺序表中第i个位置的元素修改成key
//第i个位置就是下标i-1的位置
bool SqListByLocationUpdate(SqList &L,int key,int i){
    //判断修改的位置是否正确
    if(i<1||i>L.length){
        return false;
    }
    //将下标i-1的元素修改成key
    L.R[i-1] = key;
    return true;
}

1.1.9 顺序表的按值修改元素

顺序表的按值修改指的是根据元素的值修改元素, 顺序表的按值修改需要先按值查找元素在顺序表中的位置。顺序表的按值查找元素的位置参见1.1.3小节。找到元素的位置之后,顺序表的按值修改就转变成顺序表的按位置修改。顺序表的按位置修改元素参见1.1.8小节。顺序表的按值修改代码如下:

//将顺序表中值为value的元素修改成key
//第i个位置就是下标i-1的位置
bool SqListByValueUpdate(SqList &L,int value,int key){
    //查找value在顺序表中的位置i
    int i = SqListByValueSelect(L,value);
    //如果i等于-1说明指定元素value不存在
    if(i==-1){
        return false;
    }
    //将下标i-1的元素修改成key
    L.R[i-1] = key;
    return true;
}