特点
- 顺序表是有序、有限,且元素数据类型相同的集合。
- 除第一个元素外,其他元素都有唯一的前驱元素。
- 除最后一个元素外,其他的元素都有唯一的后继元素。
- 顺序表中的元素总数
n(n ≥ 0)
即为顺序表的长度,n = 0
时,顺序表的长度为0,为空表。
功能实现
定义
#define SUC 1 // 定义SUC 作为状态返回值,成功
#define ERR 0 // 定义ERR 作为状态返回值,错误
#define TRUE 1 // 定义TRUE 作为真假返回值,真
#define FALSE 0 // 定义FALSE 作为真假返回值,假
#define MAXSIZE 20 // 定义MAXSIZE为存储空间最大容量,依据情况而定
typedef int Status; // 定义Status作为状态返回类型
typedef int Bool; // 定义Bool 作为判断真假返回类型
typedef int ElemType ; // ElemType 表示表中元素数据类型,依据情况而定
typedef struct // 定义存储结构
{
ElemType data[MAXSIZE]; // 定义数组,作为顺序表的存储结构
int len; // 定义len,表示【顺序表】长度
} SqList;
函数
初始化
功能:将顺序表长度初始化为0。
参数类型:SqList*
返回值类型:Status
Status InitList(SqList* L)
{
L->len = 0;
return SUC;
}
重置表
功能:将顺序表长度重置为0,置为空表,该操作是对于以创建顺序表的操作。
参数类型:SqList*
返回值类型:Status
Status ResetList(SqList* L)
{
L->len = 0;
return SUC;
}
获取表长
功能:获取顺序表的长度。
参数类型:SqList
返回值类型:int
int ListLength(SqList L)
{
return L.len;
}
判断是否为空表
功能:判断顺序表是否为空表
参数类型:SqList
返回值类型:Bool
Bool isEmpty(SqList L)
{
return L.len == 0 ? TRUE : FALSE;
}
访问元素
功能:输出指定元素至控制台
参数类型:ElemType
返回值类型:Status
Status visit(ElemType e)
{
printf("%d ",e);
return SUC;
}
遍历顺序表
功能:遍历顺序表中每个元素
参数类型:SqList
返回值类型:Status
Status ListTraverse(SqList L)
{
int i = 0;
int len = L.len;
for(i = 0; i < len; i++)
{
visit(L.data[i]);
}
printf("\n");
return SUC;
}
获取元素
功能:将指定位置上的元素的值赋值给接收元素
参数类型:SqList
、ElemType*
(接收元素)、int
(位置)
返回值:Status
说明:
- 判断顺序表是否为空表?为空表返回ERR
- 判断指定位置是否合法?非法返回ERR
Status GetElem(SqList L, ElemType* e, int p)
{
if(L.len == 0 || p < 1 || p > L.len)
{
return ERR;
}
*e = L.data[p - 1];
return SUC;
}
查找元素
功能:查找指定元素在顺序表中的位置
参数类型:SqList
、ElemType
返回值:int
说明:
- 判断顺序表是否为空表,空表返回0
- 遍历顺序表查找到则返回该位置,否则返回0
int LocataElem(SqList L, ElemType e)
{
if(L.len == 0)
{
return 0; // 空表返回0
}
int i = 0;
for(i = 0; i < L.len; i++)
{
if(L.data[i] == e)
return i + 1; // 找到则返回位置
}
return 0; // 找不到则返回0
}
头插
功能:将元素添加至顺序表头。
参数类型:SqList*
、ElemType
(添加的元素)
返回值类型:Status
说明:
- 判断顺序表是否已满
- 将所有元素整体后移一位
- 将元素添加至表头,表长+1
Status PushFront(SqList* L, ElemType e)
{
int i = 0;
if (L->len == MAXSIZE) // 判断顺序表是否已满
{
return ERR;
}
for (i = L->len - 1; i >= 0; i--)
{
L->data[i + 1] = L->data[i]; // 将所有元素整体后移一位
}
L->data[0] = e; // 将元素添加至表头
L->len++; // 表长+1
return SUC;
}
尾插
功能:判断将元素添加至表尾
参数类型:SqList*
、ElemType
(添加的元素)
返回值类型:Status
说明:
- 判断顺序表是否已满
- 将元素添加至表尾,表长+1
Status PushBack(SqList* L, ElemType e)
{
if (L->len == MAXSIZE)
{
return ERR; // 顺序表已满,则返回ERR
}
L->data[L->len] = e; // 将元素添加至尾部,L->len是顺序表最后一个元素后一个位置,即表尾
L->len++; // 顺序表长度+1
return SUC;
}
指定位置插入元素
功能:将元素添加至顺序表中指定位置。
参数类型:SqList*
、ElemType
(添加的元素)、int
(位置)
返回值类型:Status
说明:
在添加元素前需要判断三点:
-
当前顺序表是否已满?
-
添加的位置是否不合理?
-
判断添加的位置是否在表尾?
如果在表尾添加元素则不需要移动表中其他元素,否则需要将添加位置后的所有元素整体向后移动一位(包括添加位置的当前元素)。
添加完毕后,将表长+1,返回SUC
。
Status InsertPos(SqList* L, ElemType e, int p)
{
if (L->len == MAXSIZE || p < 1 || p > L->len + 1) // 判断顺序表是否已满,或则插入位置是否合理
{ // L->len+1, 连续线性表,中间不能存在空位置
return ERR;
}
if (p <= L->len) // 判断添加位置是否在表尾,表尾不需要移动表中其他元素
{ // 进入语句,说明p不在表尾
int i = 0;
for (i = L->len - 1; i >= p - 1; i--)
{
L->data[i + 1] = L->data[i]; // 则需要将添加位置后的所有元素向后移动一位
}
}
L->data[p - 1] = e; // 将指定元素添加到指定位置
L->len++; // 表长+1
return SUC;
}
头删
功能:将顺序表头的元素删除
参数类型:SqList*
、 ElemType*
(接收删除的元素)
返回值类型:Status
说明:
- 判断表是否为空,为空返回ERR;
- 将顺序表说有元素整体前移一位
- 顺序表长度-1
Status PopFront(SqList* L, ElemType* e)
{
if (L->len == 0)
return ERR; // 顺序表为空,返回ERR
*e = L->data[0]; // 将被删除的元素赋值给*e
int i = 0;
for (i = 0; i < L->len - 1; i++)
{
L->data[i] = L->data[i + 1]; // 将所有元素整体前移一位
}
L->len--; // 顺序表长度减1
return SUC; // 返回SUC
}
尾删
功能:将顺序表尾的元素删除
参数类型:SqList*
、 ElemType*
(接收删除的元素)
返回值类型:Status
说明:
- 判断表是否为空,为空返回ERR
- 变量接收被删除的元素
- 顺序表长度-1
Status PopBack(SqList* L, ElemType* e)
{
if (L->len == 0)
return ERR; // 顺序表为空,返回ERR
*e = L->data[L->len - 1]; // 被删除的元素赋值给*e, L->len - 1为最后一个元素的下标
L->len--; // 将表长-1,达到删除表尾元素目的
return SUC;
}
指定位置删除元素
功能:删除顺序表指定位置元素
参数类型:SqList*
、ElemType*
(接收删除的元素)、int
(指定删除的位置)
返回值类型:Status
说明:
- 判断表是否为空,或者删除位置是否合法,如果为真,则返回ERR。
- 将被删除的元素赋值给外部变量。
- 判断删除位置是否为最后一个元素,若不是是最后一个元素则将删除位置后的所有元素整体前移一位。
- 顺序表长度-1。
- 返回SUC。
Status DeletePos(SqList* L, ElemType* e, int p)
{
if (L->len == 0 || p < 1 || p > L->len) // 判断表是否为空,或者位置是否合法
return ERR;
*e = L->data[p - 1]; // 将被删除的元素赋值给*e
if (p < L->len) // 判断删除位置是否为最后一个元素
{
int i = 0;
for (i = p; i < L->len; i++)
{
L->data[i - 1] = L->data[i]; // 若不是最后一个元素则将删除位置后的所有元素整体前移一位
}
}
L->len--;
return SUC;
}
指定元素删除
功能:将指定的元素从顺序表中删除
参数类型:SqList*
、ElemType
(指定删除元素)
返回值类型:Status
说明:
- 调用
LocataElem()
函数获取指定元素的位置 - 如果
LocataElem()
的返回值不为 0,调用DeletePos
() 函数将指定元素删除,并返回SUC - 否则返回ERR;
Status DeleteElem(SqList* L, ElemType* e)
{
int p = LocataElem(*L, *e);
if (p)
{
DeletePos(L, e, p);
return SUC;
}
return ERR;
}
合并表
功能:将存在于表b
,不存在于表a
的元素,添加进表a
末尾
参数类型:SqList*
、SqList
返回值类型:void
说明:
- 访问
表b
中的问一个元素,需要用到GetElem()
函数。 - 将获取的元素与
La
中的每一个元素进行对比。需要用到LocateElem()
。 LocateElem()
的返回值为0,则说明La中不存在这个元素。- 调用
PushBack()
函数,将该元素添加至La表尾.
void UnionList(SqList* La, SqList Lb)
{
ElemType e; // 元素e 用来比较两表中是否存在元素e
// 获取两个表的长度
int La_len = La->len;
int Lb_len = Lb.len;
int i = 0;
for (i = 1; i <= Lb_len; i++) // 获取Lb中的每一个元素
{
GetElem(Lb, &e, i);
if (!LocataElem(*La, e)) // 如果La中没有该元素,将该元素添加至表尾。
{
PushBack(La, e);
}
}
}
测试代码
#define SUC 1 // 定义SUC 作为状态返回值,成功
#define ERR 0 // 定义ERR 作为状态返回值,错误
#define TRUE 1 // 定义TRUE 作为真假返回值,真
#define FALSE 0 // 定义FALSE 作为真假返回值,假
#define MAXSIZE 20 // 定义MAXSIZE为存储空间最大容量,依据情况而定
typedef int Status; // 定义Status作为状态返回类型
typedef int Bool; // 定义Bool 作为判断真假返回类型
typedef int ElemType ; // ElemType 表示表中元素数据类型,依据情况而定
typedef struct // 定义存储结构
{
ElemType data[MAXSIZE]; // 定义数组,作为线性表的存储结构
int len; // 定义len,表示【线性表】长度
} SqList;
// 初始化
Status InitList(SqList* L)
{
L->len = 0; // 将表长初始化为0,该操作是是对于新创建的表
return SUC;
}
// 重置表
Status ResetList(SqList* L)
{
L->len = 0; // 将顺序表长度重置为0,置为空表,该操作是对于以创建顺序表的操作。
return SUC;
}
// 判断是否为空表
Bool isEmpty(SqList L)
{
return L.len == 0 ? TRUE : FALSE;
}
// 获取表长
int ListLength(SqList L)
{
return L.len;
}
// 访问元素
Status visit(ElemType e)
{
printf("%d ", e); // 打印元素
return SUC;
}
// 遍历表
Status ListTraverse(SqList L)
{
int i = 0;
int len = L.len;
for (i = 0; i < len; i++)
{
visit(L.data[i]); // 调用visit函数依次打印顺序表中的元素
}
printf("\n");
return SUC;
}
// 获取元素
Status GetElem(SqList L, ElemType* e, int p)
{
if (L.len == 0 || p < 1 || p > L.len)
{
return ERR; // 空表,或位置不合法返回ERR
}
*e = L.data[p - 1]; // 将指定位置的元素赋值给e,e为真正的返回值
return SUC; // SUC为返回的状态
}
// 查找元素
int LocataElem(SqList L, ElemType e)
{
if (L.len == 0)
{
return 0; // 空表返回0
}
int i = 0;
for (i = 0; i < L.len; i++)
{
if (L.data[i] == e)
return i + 1; // 找到则返回位置
}
return 0; // 找不到则返回0
}
// 头插
Status PushFront(SqList* L, ElemType e)
{
int i = 0;
if (L->len == MAXSIZE)
{
return ERR; // 顺序表已满,则返回ERR
}
for (i = L->len - 1; i >= 0; i--)
{
L->data[i + 1] = L->data[i]; // 将所有元素整体后移一位
}
L->data[0] = e; // 将元素添加至表头
L->len++; // 表长+1
return SUC;
}
// 尾插
Status PushBack(SqList* L, ElemType e)
{
if (L->len == MAXSIZE)
{
return ERR; // 顺序表已满,则返回ERR
}
L->data[L->len] = e; // 将元素添加至尾部,L->len是顺序表最后一个元素后一个位置,即表尾
L->len++; // 顺序表长度+1
return SUC;
}
// 按位置插入
Status InsertPos(SqList* L, ElemType e, int p)
{
if (L->len == MAXSIZE || p < 1 || p > L->len + 1) // 判断顺序表是否已满,或则插入位置是否合理
{ // L->len+1, 连续线性表,中间不能存在空位置
return ERR;
}
if (p <= L->len) // 判断添加位置是否在表尾,表尾不需要移动表中其他元素
{ // 进入语句,说明p不在表尾
int i = 0;
for (i = L->len - 1; i >= p - 1; i--)
{
L->data[i + 1] = L->data[i]; // 则需要将添加位置后的所有元素向后移动一位
}
}
L->data[p - 1] = e; // 将指定元素添加到指定位置
L->len++; // 表长+1
return SUC;
}
// 头删
Status PopFront(SqList* L, ElemType* e)
{
if (L->len == 0)
return ERR; // 顺序表为空,返回ERR
*e = L->data[0]; // 将被删除的元素赋值给*e
int i = 0;
for (i = 0; i < L->len - 1; i++)
{
L->data[i] = L->data[i + 1]; // 将所有元素整体前移一位
}
L->len--; // 顺序表长度减1
return SUC; // 返回SUC
}
// 头删
Status PopBack(SqList* L, ElemType* e)
{
if (L->len == 0)
return ERR; // 顺序表为空,返回ERR
*e = L->data[L->len - 1]; // 被删除的元素赋值给*e, L->len - 1为最后一个元素的下标
L->len--; // 将表长-1,达到删除表尾元素目的
return SUC;
}
// 指定位置删除
Status DeletePos(SqList* L, ElemType* e, int p)
{
if (L->len == 0 || p < 1 || p > L->len) // 判断表是否为空,或者位置是否合法
return ERR;
*e = L->data[p - 1]; // 将被删除的元素赋值给*e
if (p < L->len) // 判断删除位置是否为最后一个元素
{
int i = 0;
for (i = p; i < L->len; i++)
{
L->data[i - 1] = L->data[i]; // 若不是最后一个元素则将删除位置后的所有元素整体前移一位
}
}
L->len--;
return SUC;
}
// 指定元素删除
Status DeleteElem(SqList* L, ElemType* e)
{
int p = LocataElem(*L, *e);
if (p)
{
DeletePos(L, e, p);
return SUC;
}
return ERR;
}
// 合并表
void UnionList(SqList* La, SqList Lb)
{
ElemType e; // 元素e 用来比较两表中是否存在元素e
// 获取两个表的长度
int La_len = La->len;
int Lb_len = Lb.len;
int i = 0;
for (i = 1; i <= Lb_len; i++) // 获取Lb中的每一个元素
{
GetElem(Lb, &e, i);
if (!LocataElem(*La, e)) // 如果La中没有该元素,将该元素添加至表尾。
{
PushBack(La, e);
}
}
}
int main()
{
// 创建顺序表La,Lb
SqList La,Lb;
// 创建接收ElemType类型变量
ElemType elem;
// 创建循环变量
int i = 0;
// 创建接收状态变量
Status s = 0;
// 创建接收真值变量
Bool b = 0;
// 创建接收int返回值变量
int ret = 0;
// 初始化顺序表La
InitList(&La);
// 在顺序表La的表头插入5个元素
for (i = 1; i <= 5; i++)
{
PushFront(&La, i);
}
printf("1. 表头添加元素后:");
ListTraverse(La);
// 删除表头元素
s = PopFront(&La,&elem);
// 判断删除是否成功
if (s)
{
printf("2. 被删除的元素是:%d\n", elem);
printf("3. 删除表头元素后:");
ListTraverse(La);
// 获取顺序表当前长度
ret = ListLength(La);
printf("4. 顺序表当前长度为:%d\n", ret);
}
else
{
printf("2. 删除失败!\n");
}
// 重置顺序表
s = ResetList(&La);
printf("5. 顺序表是否重置成功?ret = %d(1. 成功 0. 失败)\n", s);
// 判断顺序表是否为空
b = isEmpty(La);
printf("6. 顺序表是否为空? bl = %d(1. 是 0. 否)\n", b);
// 再次在La的表尾处插入10个元素
for (i = 1; i <= 10; i++)
{
PushBack(&La, i);
}
printf("7. 表尾添加元素后:");
ListTraverse(La);
// 删除表尾元素
s = PopBack(&La, &elem);
// 判断删除是否成功
if (s)
{
printf("8. 被删除的元素是:%d\n", elem);
printf("9. 删除表尾元素后:");
ListTraverse(La);
// 获取顺序表当前长度
ret = ListLength(La);
printf("10. 顺序表当前长度为:%d\n", ret);
}
else
{
printf("8. 删除失败!\n");
}
// 在指定位置插入元素
for (i = 5; i <= 8; i++)
{
InsertPos(&La, 233, i);
}
printf("11. 指定位置插入元素后:");
ListTraverse(La);
// 在指定位置删除元素
printf("12. 指定位置被删除元素是:");
for (i = 1; i <= 3; i++)
{
DeletePos(&La, &elem, i);
printf("%d ", elem);
}
printf("\n13. 删除指定位置的元素后:");
ListTraverse(La);
// 获取顺序表当前长度
ret = ListLength(La);
printf("14. 顺序表当前长度为:%d\n", ret);
// 获取指定位置的元素
printf("15. 查找指定位置元素为:");
for (i = 0; i < 3; i++)
{
s = GetElem(La, &elem, i);
if (s)
{
printf("%d ", elem);
}
else
{
printf("该元素不存在! ");
}
}
// 查找元素
elem = 233;
ret = LocataElem(La, elem);
printf("\n16. 查找元素%d的位置在:第%d个\n", elem, ret);
// 删除指定元素
s = DeleteElem(&La, &elem);
if (s)
{
printf("17. 删除元素%d成功!\n", elem);
}
else
{
printf("17. 删除失败!\n");
}
printf("18. 删除指定元素后:");
ListTraverse(La);
// 获取顺序表当前长度
ret = ListLength(La);
printf("19. 顺序表当前长度为:%d\n", ret);
// 初始化顺序表Lb
InitList(&Lb);
// 表尾插入元素
for (i = 5; i <= 15; i++)
{
PushBack(&Lb, i);
}
printf("20. 在表Lb的尾部插入元素后:");
ListTraverse(Lb);
// 合并表,将Lb中存在,la中不存在的添加到La中
UnionList(&La, Lb);
printf("21. 两表合并后La表的元素有:");
ListTraverse(La);
return 0;
}