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