线性表
线性表
1. 基本概念
线性表是包含若干数据元素的一个线性序列,记为:\(L=(a_0,...a_{i-1},a_i,a_{i+1}...a_{n-1})\)
其中,L为表名,\(a_i(0\leq i\leq n-1)\)为数据元素;n为表长,n>0时,线性表为非空表,否则为空表。
二元组形式表述:
$$L=(D,R)$$
即线性表L包含数据元素集合D和关系集合R
$$D = { a_i| a_i\in datatype , i =0,1,2,...n-1,n\geq0 }$$
$$R={<a_i,a_{i+1}> | a_i,a_{i+1}\in D, 0\leq i\leq n-2}$$
关系符\(<a_i,a_{i+1}>\)称为有序对,表示任意相邻的两个元素之间的一种先后次序,\(a_i\)是\(a_{i+1}\)的直接前驱,\(a_i+1\)是\(a_{i}\)的直接后继。
线性表的特征:
- 对非空表,\(a_0\)是表头,无前驱;
- \(a_{n-1}\)是表尾,无后继;
- 其它的每个元素\(a_i\)有且仅有一个直接前驱\(a_{i-1}\)和一个直接后继\(a_{i+1}\)。
优缺点:
1.优点,线性表的顺序存储结构存储密度高、能够随机存取;
2.缺点,要求系统提供一片较大的连续存储空间;
3.插入、删除等运算耗时,且元素在存储器中要成片移动。
2. 实现
结果:

源码如下:
sqlist.h
typedef int data_t; // 定义表内元素的数据类型
#define N 128 // 线性表最大长度
// 线性表结构体定义
typedef struct {
data_t data[N]; // data[] 表示线性表内数据
int last; // last 表示线性表长度,last = -1 表示线性表为空
}sqlist, *sqlink; // sqlist表示表的结构体类型别名,sqlink表示表的指针类型别名
// 线性表操作,需判断表是否存在
sqlink list_create(); // 创建线性表,长度为 N ,初始化数据为0,返回值为表地址
int list_clear(sqlink L); // 清空线性表,将线性表内所有数据置0,返回值 0 表清空成功 -1 表清空失败
int list_free(sqlink L); // 销毁(释放)线性表,返回值 0 表销毁成功 -1 表清空失败
int list_show(sqlink L); // 输出线性表内所有元素,返回值 0 遍历成功 -1 表不存在或为空,为空时会输出提示信息
// 线性表内数据变动,已确认过线性表存在,不再做判断
int list_empty(sqlink L); // 判断线性表是否为空,返回值 0 表非空 1 表为空表
int list_length(sqlink L); // 获取线性表长度,返回值为 表长度
int list_locate(sqlink L, data_t value); // 获取线性表中值为 value 的元素位置,返回值 value 的元素位置 , -1 未找到对应元素,并输出元素不在表中
int list_insert(sqlink L, data_t value, int pos); // 在线性表中插入值为 value 的元素,pos 为插入位置,返回值 0 表示插入成功 -1 表示表已装满或插入位置不合法,并且会输出错误信息
int list_delete(sqlink L,int pos); // 在线性表中删除 pos 位置的元素,返回值 0 删除成功 -1 表为空在或位置不合法,并且会输出错误信息
int list_merge(sqlink L1, sqlink L2); // 合并线性表 L1 和 L2 ,即二者取并集,返回值 0 两表合并成功 -1 两表合并失败,L1已装满
int list_purge(sqlink L); // 删除线性表中重复元素,
sqlist.c
#include "sqlist.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/**
* @name list_create()
* @brief 创建线性表函数,长度为 N ,初始化数据为 0
* @param 无
* @retval 表地址
*/
sqlink list_create()
{
// 1. 先分配内存给线性表
sqlink L;
L = (sqlink)malloc(sizeof(sqlist));
// 2. 判断为表分配空间是否成功
if (L == NULL)
{
printf("list malloc failed\n");
return L;
}
// 3. 表分配空间成功,初始化表内数据全为0
memset(L, 0, sizeof(sqlist));
L->last = -1;
// 4. 返回表地址
return L;
}
/**
* @name list_clear()
* @brief 线性表清空函数
* @param L 表地址
* @retval 0 表清空成功 -1 表清空失败
*/
int list_clear(sqlink L)
{
// 1. 判断表地址是否为空,即表是否存在
if (L == NULL)
return -1;
// 2. 表内所有数据填充为0
memset(L, 0, sizeof(sqlist));
// 将last指定的末尾数据指向为-1
L->last = -1;
return 0;
}
/**
* @name list_free()
* @brief 线性表销毁函数
* @param L 表头地址
* @retval 0 表销毁成功 -1 表清空失败
*/
int list_free(sqlink L)
{
// 1. 判断表地址是否为空,即表是否存在,然后进行空间释放
if (L == NULL)
return -1;
else
{
free(L); // 通过free函数释放内存
L = NULL; // 将L指向为NULL
return 0;
}
}
/**
* @name list_show()
* @brief 遍历表,输出表内所有数据
* @param L 表头地址
* @retval 0 遍历成功 -1 表不存在或为空,为空时会输出提示信息
*/
int list_show(sqlink L)
{
// 1. 判断表地址是否为空,即表是否存在
if (L == NULL)
return -1;
// 2. 判断表内数据是否为空,为空时输出提示信息并返回-1
if (L->last == -1)
{
printf("list is empty\n");
return -1;
}
// 3. 遍历输出表内所有数据
for (data_t i = 0; i <= L->last; i++)
{
printf("%d ", L->data[i]);
}
puts("");
return 0;
}
/**
* @name list_empty()
* @brief 判断表是否为空函数
* @param L 表头地址
* @retval 0 表非空 1 表为空表
*/
int list_empty(sqlink L)
{
if (L->last == -1)
return 1;
else
return 0;
}
/**
* @name list_length()
* @brief 获取表长度函数
* @param L 表头地址
* @retval 表长度
*/
int list_length(sqlink L)
{
return L->last + 1;
}
/**
* @name list_locate()
* @brief 获取线性表中值为 value 的元素位置
* @param L 表头地址, value 需要查询的元素
* @retval value 的元素位置 , -1 未找到对应元素,并输出元素不在表中
*/
int list_locate(sqlink L, data_t value)
{
for (int i = 0; i <= L->last; i++)
{
if (L->data[i] == value)
{
return i;
}
}
// printf("value is not in list\n");
return -1;
}
/**
* @name list_insert()
* @brief 往表内插入一个数据
* @param L 表头地址, value 插入的值, pos 插入位置
* @retval 0 表示插入成功 -1 表示表已装满或插入位置不合法,并且会输出错误信息
*/
int list_insert(sqlink L,data_t value, int pos)
{
// 1. 判断表是否装满,装满的表无法再插入数据,否则会内存越界
if (L->last == N-1)
{
printf("list is full\n");
return -1;
}
// 2. 判断插入位置是否合法,插入位置不能超过表的长度,[0,last+1]
if (pos < 0 || pos > L->last+1)
{
printf("Pos is invalid\n");
return -1;
}
// 3. 循环将插入位置后面的数据往后移动一位
for (int i = L->last; i >= pos; i--)
{
L->data[i+1] = L->data[i];
}
// 4. 将插入位置的数据设置为插入的值,将last下标加1
L->data[pos] = value;
L->last++;
return 0;
}
/**
* @name list_delete()
* @brief 遍历表,输出表内所有数据
* @param L 表头地址,pos 删除位置
* @retval 0 删除成功 -1 表为空在或位置不合法,并且会输出错误信息
*/
int list_delete(sqlink L,int pos)
{
// 1. 判断表是否为空,空表无法删除数据
if (L->last == -1)
{
printf("list is empty\n");
return -1;
}
// 2. 判断删除位置是否合法,插入位置不能超过表的长度,[0,last]
if (pos < 0 || pos > L->last)
{
printf("Pos is invalid\n");
return -1;
}
// 3. 循环将删除位置后面的数据往前移动一位
for (int i = pos+1; i <= L->last; i++)
{
L->data[i-1] = L->data[i];
}
// 4. 更新表数据
L->last--;
return 0;
}
/**
* @name list_merge()
* @brief 合并线性表 L1 和 L2 ,即二者取并集
* @param L1 表头地址 L2 表头地址
* @retval 0 两表合并成功 -1 两表合并失败,L1已装满
*/
int list_merge(sqlink L1, sqlink L2)
{
int i = 0;
int ret;
while (i <= L2->last)
{
ret = list_locate(L1, L2->data[i]);
if (ret == -1)
{
if (list_insert(L1, L2->data[i], L1->last+1) == -1) // 判断表L1是否已装满
return -1;
}
i++;
}
return 0;
}
/**
* @name list_purge()
* @brief 删除线性表中重复元素
* @param L 表头地址
* @retval 0
*/
int list_purge(sqlink L)
{
int i,j;
// 1. 判断表是否为空,空表无法删除数据
if (L->last == 0)
{
return 0;
}
// 2. 循环删除重复元素
i = 1;
while (i <= L->last)
{
j = i - 1;
while (j >=0)
{
if (L->data[i] == L->data[j])
{
list_delete(L, i);
break;
}
else
{
j--;
}
}
if (j < 0)
{
i++;
}
}
return 0;
}
main.c
#include <stdio.h>
#include "sqlist.h"
void test_insert();
void test_delete();
void test_merge();
void test_purge();
int main(int argc, const char *argv[])
{
test_insert();
test_delete();
test_merge();
test_purge();
return 0;
}
void test_insert()
{
sqlink L;
L = list_create();
if (L == NULL)
{
return;
}
list_insert(L, 1, 0);
list_insert(L, 2, 0);
list_insert(L, 3, 0);
list_insert(L, 4, 0);
list_insert(L, 5, 0);
list_insert(L, 999, 3);
list_show(L);
list_free(L);
}
void test_delete()
{
sqlink L;
L = list_create();
if (L == NULL)
{
return;
}
list_insert(L, 1, 0);
list_insert(L, 2, 0);
list_insert(L, 3, 0);
list_insert(L, 4, 0);
list_insert(L, 5, 0);
list_insert(L, 999, 3);
list_delete(L, 3);
list_show(L);
list_delete(L, 9);
list_free(L);
}
void test_merge()
{
sqlink L1, L2;
L1 = list_create();
if (L1 == NULL)
{
return;
}
L2 = list_create();
if (L2 == NULL)
{
return;
}
list_insert(L1, 7, 0);
list_insert(L1, 13, 0);
list_insert(L1, 37, 0);
list_insert(L1, 58, 0);
list_insert(L1, 19, 0);
list_insert(L2, 7, 0);
list_insert(L2, 13, 0);
list_insert(L2, 2, 0);
list_insert(L2, 8, 0);
list_insert(L2, 19, 0);
list_show(L1);
list_show(L2);
printf("********************\n");
list_merge(L1, L2);
list_show(L1);
list_show(L2);
list_free(L1);
list_free(L2);
}
void test_purge()
{
sqlink L;
L = list_create();
if (L == NULL)
{
return;
}
list_insert(L, 1, 0);
list_insert(L, 2, 0);
list_insert(L, 3, 0);
list_insert(L, 4, 0);
list_insert(L, 5, 0);
list_insert(L, 7, 0);
list_insert(L, 4, 0);
list_insert(L, 5, 0);
list_show(L);
printf("********************\n");
list_purge(L);
list_show(L);
list_free(L);
}

浙公网安备 33010602011771号