Skip to content

LV020-顺序表操作

这一部分主要是对顺序表各种操作的实现,例如顺序表的创建,插入,显示,删除,释放,去重等操作。

一、顺序表的创建

1.创建步骤

image-20220929161556161

注意

(1) L-> last 的值代表了 data [N] 中最后一个 有效数据 的下标,后边的图会用箭头来指示,但是它并不是指针,若将 L-> last 加上 1 ,就可以得到数组有效元素的个数。

(2)创建线性表的时候用到了 malloc 和 memset 两个函数,需要加上两个函数对应的头文件。

2. 函数实现

c
/**
 * @Function   : seqlist_create
 * @brief      : 创建一个顺序表
 * @param arg  : none
 * @return     : seqlistlink 类型,返回创建的顺序表首地址
 * @Description:
 */
_seqlistlink seqlist_create(void)
{
    /* 0.相关变量定义 */
    _seqlistlink L; /* 定义一个结构体指针变量 L */
    /* 1. malloc 申请顺序表内存空间 */
    L = (_seqlistlink)malloc(sizeof(_seqlist)); /* stdlib.h 头文件中的函数 */
    /* 2. 判断是否申请成功 */
    if (L == NULL)
    {
        printf("[ERROR]sequence list malloc failed!\n");
        return L;
    }
    /* 3.申请的内存空间初始化 */
    memset(L, 0, sizeof(_seqlist)); /* string.h 头文件中的函数,数组元素全部赋值为 0 */
    L->last = -1;                  /* 空表时为 -1 */
    return L;
}

二、顺序表的释放

1. 释放步骤

image-20220929164701834

注意

(1)释放的时候直接释放顺序表结构体指针变量指向的内存空间即可。

(2)可以判断一下要释放的顺序表是否存在。

2.函数实现

c
/**
 * @Function   : seqlist_free
 * @brief      : 释放顺序表占用的内存空间
 * @param L    : _seqlistlink 类型,表示要释放的顺序表的首地址
 * @return     : int 类型,顺序表不存在返回-1, 释放完成返回 0
 * @Description: 
 */
int seqlist_free(_seqlistlink L)
{
	if (L == NULL)
		return -1;
	free(L);
	L = NULL;
	return 0;
}

三、顺序表的长度

1. 求表长度步骤

image-20220929170123005

从上图可以看出,其实整个顺序表的长度是顺序表结构体成员 last 来决定的,它决定了顺序表中有效数据元素的个数,只要它是 -1,就代表顺序表中没有数据,即便是顺序表中的数据有一个值,但是我们依然认为这是一个空表。

注意】 为了使 last 成员可以和数组最后一个元素的下表对应,设置了初始的 last 成员为 -1,所以 last + 1 才是实际有效元素个数。

2. 函数实现

c
/**
 * @Function   : seqlist_length
 * @brief      : 求顺序表长度
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @return     : int 类型,返回 L-> last+1, 顺序表有效元素个数; 返回-1, 顺序表地址为 NULL
 * @Description:
 */
int seqlist_length(_seqlistlink L)
{
    if (L == NULL)
        return -1;
    return (L->last + 1);
}

四、顺序表的空满

1. 空满判定步骤

image-20220929185752607

【注意】顺序表 L 的空满由 L-> last 成员决定,而非是顺序表数组成员中存储了多少个数据,

判断条件说明
L-> last = -1认为顺序表为空
L-> last = N - 1认为顺序表为满

2. 函数实现

2.1 顺序表为空判定

c
/**
 * @Function   : seqlist_empty
 * @brief      : 顺序表是否为空
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @return     : int 类型,返回 1, 表示顺序表为空; 返回 0, 表示顺序表非空
 * @Description:
 */
int seqlist_empty(_seqlistlink L)
{
    if (L->last == -1)
        return 1;
    else
        return 0;
}

2.2 顺序表为满判定

c
/**
 * @Function   : seqlist_full
 * @brief      : 顺序表是否为满
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @return     : int 类型,返回 1, 表示顺序表为满; 返回 0, 表示顺序表未满
 * @Description:
 */
int seqlist_full(_seqlistlink L)
{
    if (L->last == N - 1)
        return 1;
    else
        return 0;
}

五、顺序表的清空

1. 清空步骤

image-20220930054050126

【注意】 对于顺序表来说,里边是否存放了元素,存放了多少个元素是由顺序表中代表顺序表有效元素个数的 last 成员决定的。

判断条件说明
L-> last = -1认为顺序表为空
L-> last = N - 1认为顺序表为满

所以,对于顺序表的清空,我们只需要 将 L-> last 赋值为 -1 ,就可以认为此顺序表已经清空

2. 函数实现

c
/**
 * @Function   : seqlist_clear
 * @brief      : 顺序表清空
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @return     : int 类型,返回-1, 表示顺序表不存在,返回 0, 表示清空完成
 * @Description:
 */
int seqlist_clear(_seqlistlink L)
{
    if (L == NULL)
        return -1;

    memset(L, 0, sizeof(seqlist));
    L->last = -1;

    return 0;
}

六、顺序表数据插入

1. 数据插入步骤

insert

如上图所示,我们分为头部插入,尾部插入和中间插入,分析过后,其实可以归结为一类,就是在指定位置插入数据,头部和尾部的时候是两种特殊性情况,但是处理方式就可以与中间插入的这种普遍情况一样。一般步骤如下:

image-20220930073755707

2. 函数实现

c
/**
 * @Function   : seqlist_insert
 * @brief      : 顺序表数据按位置插入
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @param value:data_t 类型,表示要插入的数据
 * @param pos  :int 类型,表示要插入的位置, 有效区间为 [0, L-> last+1]
 * @return     : int 类型,返回 0, 表示插入成功; 返回-1, 表示插入失败
 * @Description: 
 */
int seqlist_insert(_seqlistlink L, data_t value, int pos)
{
    int i = 0;
    /* 1. 判断顺序表是否已满 */
    if (L->last == N - 1)
    {
        printf("[WARN ]sequence list is full\n");
        return -1;
    }
    /* 2. 判断插入位置是否合法 [0, L-> last+1]*/
    if (pos < 0 || pos > L->last + 1)
    {
        printf("[ERROR]pos is invalid!\n");
        return -1;
    }
    /* 3.移动插入位置后边的数据 */
    for (i = L->last; i >= pos; i--) /* L-> last 就代表了最后一个元素的下标 */
    {
        L->data[i + 1] = L->data[i]; /* pos 下标后边的数据全部后移一个位置 */
    }
    /* 4.更新数据并更新顺序表长度 */
    L->data[pos] = value;
    L->last++;

    return 0;
}

七、顺序表数据删除

1. 删除步骤

delect

有上图可知,我们删除顺序表指定位置数据的时候只需要将该位置后边所有元素前移一个位置即可,一般步骤如下:

image-20220930075917043

2. 函数实现

c
/**
 * @Function   : seqlist_delete
 * @brief      : 删除顺序表指定位置元素
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @param pos  :int 类型,表示要删除的位置, 有效区间为 [0, L-> last]
 * @return     : int 类型,返回 0, 表示删除成功; 返回-1, 表示删除失败
 * @Description:
 */
int seqlist_delete(_seqlistlink L, int pos)
{
    int i = 0;
    /* 1.判断顺序表是否为空 */
    if (L->last == -1)
    {
        printf("[WARN ]sequence list is empty!\n");
        return -1;
    }

    /* 2.判断 pos 是否合法,合法区间为 [0, L-> last] */
    if (pos < 0 || pos > L->last)
    {
        printf("[ERROR]delete pos is invalid!\n");
        return -1;
    }

    /* 3.移动删除位置后的元素以填补空缺,涉及元素区间为 [pos+1, L-> last] */
    for (i = pos + 1; i <= L->last; i++)
    {
        L->data[i - 1] = L->data[i];
    }

    /* 4.更新顺序表元素个数 */
    L->last--;

    return 0;
}

八、顺序表数据显示

1. 数据显示步骤

image-20220930090451597

对于数据的显示,我们就像对数组遍历一样,遍历整个顺序表,然后打印出数据即可。

2. 函数实现

c
/**
 * @Function   : seqlist_show
 * @brief      : 顺序表元素显示
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @return     : int 类型,返回-1, 表示顺序表不存在; 返回 0, 表示显示完毕
 * @Description:
 */
int seqlist_show(_seqlistlink L)
{
    int i;
    /* 1. 判断顺序表是否存在 */
    if (L == NULL)
        return -1;
    /* 2. 判断顺序表是否为空 */
    if (L->last == -1)
    {
        printf("[WARN ]sequence list is empty!\n");
    }
    /* 3.开始遍历顺序表中所有元素,并打印 */
    printf("sequence list:");
    for (i = 0; i <= L->last; i++)
    {
        printf("%d ", L->data[i]);
    }
    puts(""); /* 自带换行符 */

    return 0;
}

九、顺序表数据查找

1. 查找步骤

image-20220930091533839

对于顺序表中数据元素的查找,我们直接遍历整个顺序表,查看数据是否存在于顺序表中即可,若是有重复的数据,我们只返回首个出现的下标。

2. 函数实现

c
/**
 * @Function   : seqlist_locate
 * @brief      : 在顺序表中查找指定数据位置(若有重复,则显示首次出现的位置)
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @param value:data_t 类型,表示要查找的元素
 * @return     : int 类型,返回-1, 表示要查找的元素不存在或者顺序表不存在; 返回非负数, 表示要查找的数据的下标
 * @Description:
 */
int seqlist_locate(_seqlistlink L, data_t value)
{
    int i = 0;
    /* 1. 判断顺序表是否存在 */
    if (L == NULL)
        return -1;
    for (i = 0; i <= L->last; i++)
    {
        if (L->data[i] == value)
            return i;
    }

    return -1;
}

十、顺序表数据去重

1. 数据去重步骤

delete_duplicate

【思路】

对于去重,我们这里使用的方式是从第二个数据开始(下标为 1 ),逐个与前边的数据相比较,若发现与前边的某个数据重复,则将该数据删除,也就是将当前数据后边的数据逐个左移,覆盖当前数据,然后重复比较,直至到顺序表结尾。

【注意】若有重复,原本 i+1 位置的元素补到第 i 个位置,此时 i 位置上的元素需要再进行比较,所以 i 不需要往后移;若没有重复,内层循环退出后,j 的值小于 0 ,只有在此种情况下 i 才需要往后移动。

2. 函数实现

c
/**
 * @Function   : seqlist_delete_duplicate
 * @brief      : 在顺序表中删除重复元素,只保留首次出现的数据
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @return     : int 类型,返回-1, 表示顺序表不存在; 返回 0, 表示去重完成
 * @Description:
 */
int seqlist_delete_duplicate(_seqlistlink L)
{
    int i = 0;
    int j = 0;

    if (L->last == 0)
        return -1;

    i = 1;
    /* i 从 1 开始,往后移动,第 i 个数依次与它前边的比较,相同的就直接把第 i 个位置元素删除 */
    while (i <= L->last)
    {
        j = i - 1;
        while (j >= 0) /* 逐个向前比较 */
        {
            if (L->data[i] == L->data[j]) /* 若有相同的,就删除这个位置的元素,并退出比较循环 */
            {
                seqlist_delete(L, i); /* 原本 i+1 位置的元素补到第 i 个位置 */
                break;
            }
            else /* 若没有相同的,继续向前比较 */
                j--;
        }
        /* 若有重复,原本 i+1 位置的元素补到第 i 个位置,此时 i 位置上的元素需要再进行比较,所以 i 不需要往后移
           若没有重复,上边循环退出后,j 的值小于 0,只有在此种情况下才需要往后移动。 */
        if (j < 0)
            i++;
    }

    return 0;
}

十一、顺序表数据合并

1. 数据合并步骤

image-20221010084834683
  • (1)在 L1 中查找 L2 中的每个数据;
  • (2)若 L1 中已有,则继续下一个的查找,若 L1 中没有,则将此数据插入到 L1 后边。

2. 函数实现

c
/**
 * @Function   : seqlist_merge
 * @brief      : 求两个顺序表并集,保持第二个顺序表不变
 * @param L1   :_seqlistlink 类型,表示顺序表 1 地址
 * @param L2   :_seqlistlink 类型,表示顺序表 2 地址
 * @return     : int 类型,返回-1, 表示合并失败; 返回 0, 表示合并完成
 * @Description:
 */
int seqlist_merge(_seqlistlink L1, _seqlistlink L2)
{
    int i = 0;
    int ret = 0;

    while (i <= L2->last)
    {
        ret = seqlist_locate(L1, L2->data[i]);
        /* L1 中无该元素,才插入该元素 */
        if (ret == -1)
        {
            if (seqlist_insert(L1, L2->data[i], L1->last + 1) == -1)
                return -1;
        }

        i++;
    }

    return 0;
}

十二、完整程序

1. seqlist.c

c
/** ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== =
 * Copyright © hk. 2022-2025. All rights reserved.
 * File name  : seqlist.c
 * Author     : qidaink
 * Date       : 2022-09-29
 * Version    :
 * Description:
 * Others     :
 * Log        :
 * ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==
 */
#include "seqlist.h"

/**
 * @Function   : seqlist_create
 * @brief      : 创建一个顺序表
 * @param arg  : none
 * @return     : seqlistlink 类型,返回创建的顺序表首地址
 * @Description:
 */
_seqlistlink seqlist_create(void)
{
    /* 0.相关变量定义 */
    _seqlistlink L; /* 定义一个结构体指针变量 L */
    /* 1. malloc 申请顺序表内存空间 */
    L = (_seqlistlink)malloc(sizeof(_seqlist)); /* stdlib.h 头文件中的函数 */
    /* 2. 判断是否申请成功 */
    if (L == NULL)
    {
        printf("[ERROR]sequence list malloc failed!\n");
        return L;
    }
    /* 3.申请的内存空间初始化 */
    memset(L, 0, sizeof(_seqlist)); /* string.h 头文件中的函数,数组元素全部赋值为 0 */
    L->last = -1;                   /* 空表时为 -1 */
    return L;
}
/**
 * @Function   : seqlist_free
 * @brief      : 释放顺序表占用的内存空间
 * @param L    : _seqlistlink 类型,表示要释放的顺序表的首地址
 * @return     : int 类型,顺序表不存在返回-1, 释放完成返回 0
 * @Description:
 */
int seqlist_free(_seqlistlink L)
{
    if (L == NULL)
        return -1;
    free(L);
    L = NULL;
    return 0;
}
/**
 * @Function   : seqlist_length
 * @brief      : 求顺序表长度
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @return     : int 类型,返回 L-> last+1, 顺序表有效元素个数; 返回-1, 顺序表地址为 NULL
 * @Description:
 */
int seqlist_length(_seqlistlink L)
{
    if (L == NULL)
        return -1;
    return (L->last + 1);
}

/**
 * @Function   : seqlist_empty
 * @brief      : 顺序表是否为空
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @return     : int 类型,返回 1, 表示顺序表为空; 返回 0, 表示顺序表非空
 * @Description:
 */
int seqlist_empty(_seqlistlink L)
{
    if (L->last == -1)
        return 1;
    else
        return 0;
}

/**
 * @Function   : seqlist_full
 * @brief      : 顺序表是否为满
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @return     : int 类型,返回 1, 表示顺序表为满; 返回 0, 表示顺序表未满
 * @Description:
 */
int seqlist_full(_seqlistlink L)
{
    if (L->last == N - 1)
        return 1;
    else
        return 0;
}

/**
 * @Function   : seqlist_clear
 * @brief      : 顺序表清空
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @return     : int 类型,返回-1, 表示顺序表不存在,返回 0, 表示清空完成
 * @Description:
 */
int seqlist_clear(_seqlistlink L)
{
    if (L == NULL)
        return -1;

    memset(L, 0, sizeof(_seqlist));
    L->last = -1;

    return 0;
}
/**
 * @Function   : seqlist_insert
 * @brief      : 顺序表数据按位置插入
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @param value:data_t 类型,表示要插入的数据
 * @param pos  :int 类型,表示要插入的位置, 有效区间为 [0, L-> last+1]
 * @return     : int 类型,返回 0, 表示插入成功; 返回-1, 表示插入失败
 * @Description:
 */
int seqlist_insert(_seqlistlink L, data_t value, int pos)
{
    int i = 0;
    /* 1. 判断顺序表是否已满 */
    if (L->last == N - 1)
    {
        printf("[WARN ]sequence list is full\n");
        return -1;
    }
    /* 2. 判断插入位置是否合法 [0, L-> last+1]*/
    if (pos < 0 || pos > L->last + 1)
    {
        printf("[ERROR]pos is invalid!\n");
        return -1;
    }
    /* 3.移动插入位置后边的数据 */
    for (i = L->last; i >= pos; i--) /* L-> last 就代表了最后一个元素的下标 */
    {
        L->data[i + 1] = L->data[i]; /* pos 下标后边的数据全部后移一个位置 */
    }
    /* 4.更新数据并更新顺序表长度 */
    L->data[pos] = value;
    L->last++;

    return 0;
}

/**
 * @Function   : seqlist_delete
 * @brief      : 删除顺序表指定位置元素
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @param pos  :int 类型,表示要删除的位置, 有效区间为 [0, L-> last]
 * @return     : int 类型,返回 0, 表示删除成功; 返回-1, 表示删除失败
 * @Description:
 */
int seqlist_delete(_seqlistlink L, int pos)
{
    int i = 0;
    /* 1.判断顺序表是否为空 */
    if (L->last == -1)
    {
        printf("[WARN ]sequence list is empty!\n");
        return -1;
    }

    /* 2.判断 pos 是否合法,合法区间为 [0, L-> last] */
    if (pos < 0 || pos > L->last)
    {
        printf("[ERROR]delete pos is invalid!\n");
        return -1;
    }

    /* 3.移动删除位置后的元素以填补空缺,涉及元素区间为 [pos+1, L-> last] */
    for (i = pos + 1; i <= L->last; i++)
    {
        L->data[i - 1] = L->data[i];
    }

    /* 4.更新顺序表元素个数 */
    L->last--;

    return 0;
}

/**
 * @Function   : seqlist_show
 * @brief      : 顺序表元素显示
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @return     : int 类型,返回-1, 表示顺序表不存在; 返回 0, 表示显示完毕
 * @Description:
 */
int seqlist_show(_seqlistlink L)
{
    int i;
    /* 1. 判断顺序表是否存在 */
    if (L == NULL)
        return -1;
    /* 2. 判断顺序表是否为空 */
    if (L->last == -1)
    {
        printf("[WARN ]sequence list is empty!\n");
    }
    /* 3.开始遍历顺序表中所有元素,并打印 */
    printf("sequence list:");
    for (i = 0; i <= L->last; i++)
    {
        printf("%d ", L->data[i]);
    }
    puts(""); /* 自带换行符 */

    return 0;
}

/**
 * @Function   : seqlist_locate
 * @brief      : 在顺序表中查找指定数据位置(若有重复,则显示首次出现的位置)
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @param value:data_t 类型,表示要查找的元素
 * @return     : int 类型,返回-1, 表示要查找的元素不存在或者顺序表不存在; 返回非负数, 表示要查找的数据的下标
 * @Description:
 */
int seqlist_locate(_seqlistlink L, data_t value)
{
    int i = 0;
    /* 1. 判断顺序表是否存在 */
    if (L == NULL)
        return -1;
    for (i = 0; i <= L->last; i++)
    {
        if (L->data[i] == value)
            return i;
    }

    return -1;
}

/**
 * @Function   : seqlist_delete_duplicate
 * @brief      : 在顺序表中删除重复元素,只保留首次出现的数据
 * @param L    : _seqlistlink 类型,表示顺序表的首地址
 * @return     : int 类型,返回-1, 表示顺序表不存在; 返回 0, 表示去重完成
 * @Description:
 */
int seqlist_delete_duplicate(_seqlistlink L)
{
    int i = 0;
    int j = 0;

    if (L->last == 0)
        return -1;

    i = 1;
    /* i 从 1 开始,往后移动,第 i 个数依次与它前边的比较,相同的就直接把第 i 个位置元素删除 */
    while (i <= L->last)
    {
        j = i - 1;
        while (j >= 0) /* 逐个向前比较 */
        {
            if (L->data[i] == L->data[j]) /* 若有相同的,就删除这个位置的元素,并退出比较循环 */
            {
                seqlist_delete(L, i); /* 原本 i+1 位置的元素补到第 i 个位置 */
                break;
            }
            else /* 若没有相同的,继续向前比较 */
                j--;
        }
        /* 若有重复,原本 i+1 位置的元素补到第 i 个位置,此时 i 位置上的元素需要再进行比较,所以 i 不需要往后移
           若没有重复,上边循环退出后,j 的值小于 0,只有在此种情况下才需要往后移动。 */
        if (j < 0)
            i++;
    }

    return 0;
}

/**
 * @Function   : seqlist_merge
 * @brief      : 求两个顺序表并集,保持第二个顺序表不变
 * @param L1   :_seqlistlink 类型,表示顺序表 1 地址
 * @param L2   :_seqlistlink 类型,表示顺序表 2 地址
 * @return     : int 类型,返回-1, 表示合并失败; 返回 0, 表示合并完成
 * @Description:
 */
int seqlist_merge(_seqlistlink L1, _seqlistlink L2)
{
    int i = 0;
    int ret = 0;

    while (i <= L2->last)
    {
        ret = seqlist_locate(L1, L2->data[i]);
        /* L1 中无该元素,才插入该元素 */
        if (ret == -1)
        {
            if (seqlist_insert(L1, L2->data[i], L1->last + 1) == -1)
                return -1;
        }

        i++;
    }

    return 0;
}

2. seqlist.h

c
/** ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== =
 * Copyright © hk. 2022-2025. All rights reserved.
 * File name  : seqlist.h
 * Author     : qidaink
 * Date       : 2022-09-29
 * Version    :
 * Description:
 * Others     :
 * Log        :
 * ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==
 */
#ifndef __SEQLIST_H__
#define __SEQLIST_H__

/* 头文件 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int data_t;

#define N 128

typedef struct __seqlist
{
    data_t data[N];
    int last;
} _seqlist, *_seqlistlink;

/* 函数声明 */

_seqlistlink seqlist_create(void);                         /* 创建一个顺序表 */
int seqlist_free(_seqlistlink L);                          /* 释放顺序表占用的内存空间 */
int seqlist_length(_seqlistlink L);                        /* 求顺序表长度 */
int seqlist_empty(_seqlistlink L);                         /* 顺序表是否为空 */
int seqlist_full(_seqlistlink L);                          /* 顺序表是否为满 */
int seqlist_clear(_seqlistlink L);                         /* 顺序表清空 */
int seqlist_insert(_seqlistlink L, data_t value, int pos); /* 顺序表数据按位置插入 */
int seqlist_delete(_seqlistlink L, int pos);               /* 删除顺序表指定位置元素 */
int seqlist_show(_seqlistlink L);                          /* 顺序表元素显示 */
int seqlist_locate(_seqlistlink L, data_t value);          /* 在顺序表中查找指定数据位置(若有重复,则显示首次出现的位置) */
int seqlist_delete_duplicate(_seqlistlink L);              /* 在顺序表中删除重复元素,只保留首次出现的数据 */
int seqlist_merge(_seqlistlink L1, _seqlistlink L2);       /* 求两个顺序表并集,保持第二个顺序表不变 */

#endif

3. Makefile

makefile
##============================================================================#
# Copyright © hk. 2022-2025. All rights reserved.
# File name  : Makefile
# Author     : qidaink
# Date       : 2022-09-29
# Version    : 
# Description: 
# Others     : 
# Log        : 
##============================================================================#
##

TARGET          := main
#============================================================================#
## 工具设置
# 设置交叉编译器名称
CROSS_COMPILE   :=
# 设置交叉编译器
CC              := $(CROSS_COMPILE)gcc
# 编译选项
CFLAGS          += -g -Wall
#============================================================================#
## 目录路径设置
# 头文件路径设置(.h)
INCDIRS 		:= .

# 源文件路径设置(.S .C)
SRCDIRS			:= .

# 生成的中间 .o 文件的位置
OBJDIRS         := .
#============================================================================#
# 生成编译器的 -I dir_path 参数 
INCLUDE			:= $(patsubst %, -I %, $(INCDIRS))

# 获取所有的 .C 文件名称(包含路径)
CFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))

# 获取所有的 .C 文件名称(不包含路径)
CFILENDIR		:= $(notdir  $(CFILES))

# 指定所有的 .C 生成的 .o 文件名(包含将要存放的路径)
COBJS			:= $(patsubst %, $(OBJDIRS)/%, $(CFILENDIR:.c=.o))

# 将所有要生成的 .o 文件合并到一个变量中(都包含路径)
OBJS			:= $(COBJS)

# 设置源文件路径
VPATH			:= $(SRCDIRS)

#============================================================================#			
# 生成目标文件	   
$(TARGET): $(OBJS)
	$(CC) $(CFLAGS) $^ -o $(TARGET)

# 隐含规则推导相关中间文件
$(COBJS) : $(OBJDIRS)/%.o : %.c
	$(CC) $(CFLAGS) -c $(INCLUDE) $<  -o $@ 
	
#============================================================================#	
.PHONY: clean clean_o
# 删除所有编译链接生成的文件命令
clean: clean_o
	@rm -vf $(TARGET)

# 删除所有的 .o 文件命令
clean_o:
	@rm -vf $(COBJS)

printf:
	@echo "CFLAGS    = $(CFLAGS)"
	@echo "INCDIRS   = $(INCDIRS)"
	@echo "SRCDIRS   = $(SRCDIRS)"
	@echo "INCLUDE   = $(INCLUDE)"
	@echo "CFILES    = $(CFILES)"
	@echo "CFILENDIR = $(CFILENDIR)"
	@echo "COBJS     = $(COBJS)"
	@echo "OBJS      = $(OBJS)"
	@echo "VPATH     = $(VPATH)"

4. main.c

c
#include <stdio.h>
#include "seqlist.h"

/* 测试函数实现 */
void test_seqlist_insert()
{
	_seqlistlink L;

	L = seqlist_create();
	if (L == NULL) return;

	seqlist_insert(L, 1, 0);
	seqlist_insert(L, 2, 1);
	seqlist_insert(L, 3, 2);
	seqlist_insert(L, 4, 2);
	seqlist_insert(L, 5, 2);

	seqlist_show(L);
	seqlist_free(L);
}

void test_seqlist_clear()
{
	_seqlistlink L;

	L = seqlist_create();
	if (L == NULL) return;

	seqlist_insert(L, 1, 0);
	seqlist_insert(L, 2, 0);
	seqlist_insert(L, 3, 0);

	seqlist_show(L);
	seqlist_clear(L);
	seqlist_show(L);

	seqlist_free(L);
}

void test_selist_delete()
{
	_seqlistlink L;

	L = seqlist_create();
	if (L == NULL) return;
	seqlist_insert(L, 1, 0);
	seqlist_insert(L, 2, 0);
	seqlist_insert(L, 3, 0);
	seqlist_insert(L, 1, 0);

	seqlist_show(L);
	seqlist_delete(L, 1);
	seqlist_show(L);
	seqlist_delete(L, 5);
	seqlist_show(L);

	seqlist_free(L);
}

void test_seqlist_empty()
{
	_seqlistlink L;

	L = seqlist_create();
	if (L == NULL) return;
	printf("list_empty(L) = %d\n", seqlist_empty(L));
	seqlist_insert(L, 1, 0);
	seqlist_insert(L, 2, 0);
	seqlist_show(L);
	printf("list_empty(L) = %d\n", seqlist_empty(L));

	seqlist_free(L);
}

void test_seqlist_length()
{
	_seqlistlink L;

	L = seqlist_create();
	if (L == NULL) return;
	printf("seqlist_length(L) = %d\n", seqlist_length(L));
	seqlist_insert(L, 1, 0);
	seqlist_insert(L, 2, 0);
	seqlist_show(L);
	printf("seqlist_length(L) = %d\n", seqlist_length(L));

	seqlist_free(L);
}

void test_seqlist_locate()
{
	_seqlistlink L;

	L = seqlist_create();
	if (L == NULL) return;
	seqlist_insert(L, 1, 0);
	seqlist_insert(L, 2, 0);
	seqlist_insert(L, 3, 0);
	seqlist_insert(L, 1, 0);
	seqlist_show(L);
	printf("list_locate(L, 1) = %d\n", seqlist_locate(L, 1));
	printf("list_locate(L, 5) = %d\n", seqlist_locate(L, 5));

	seqlist_free(L);
}

void test_seqlist_delete_duplicate()
{
	_seqlistlink L;
	L = seqlist_create();
	if (L == NULL) return;

	seqlist_insert(L, 1, 0);
	seqlist_insert(L, 1, 1);
	seqlist_insert(L, 1, 2);
	seqlist_insert(L, 2, 3);
	seqlist_insert(L, 3, 4);
	seqlist_insert(L, 4, 5);
	seqlist_insert(L, 4, 6);
	seqlist_insert(L, 5, 7);
	seqlist_insert(L, 6, 8);

	seqlist_show(L);
	seqlist_delete_duplicate(L);
	seqlist_show(L);

	seqlist_free(L);
}

void test_seqlist_merge()
{
	_seqlistlink L1;
	_seqlistlink L2;

	L1 = seqlist_create();
	L2 = seqlist_create();
	if (L1 == NULL|| L2 == NULL) return;
	seqlist_insert(L1, 1, 0);
	seqlist_insert(L1, 2, 1);
	seqlist_insert(L1, 3, 2);
	seqlist_insert(L1, 4, 3);

	seqlist_insert(L2, 4, 0);
	seqlist_insert(L2, 5, 1);
	seqlist_insert(L2, 6, 2);
	seqlist_insert(L2, 7, 3);

	seqlist_show(L1);
	seqlist_show(L2);
	printf("====================\n");
	seqlist_merge(L1, L2);
	seqlist_show(L1);
	seqlist_show(L2);

	seqlist_free(L1);
	seqlist_free(L2);
}

int main(int argc, char *argv[])
{
	// test_seqlist_insert();
	// test_seqlist_clear();
	// test_selist_delete();
	// test_seqlist_empty();
	// test_seqlist_length();
	// test_seqlist_locate();
	// test_seqlist_delete_duplicate();
	test_seqlist_merge();
    return 0;
}