线性表

线性表

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}\)的直接后继。

线性表的特征:

  1. 对非空表,\(a_0\)是表头,无前驱;
  2. \(a_{n-1}\)是表尾,无后继;
  3. 其它的每个元素\(a_i\)有且仅有一个直接前驱\(a_{i-1}\)和一个直接后继\(a_{i+1}\)

优缺点:
1.优点,线性表的顺序存储结构存储密度高、能够随机存取;
2.缺点,要求系统提供一片较大的连续存储空间;
3.插入、删除等运算耗时,且元素在存储器中要成片移动。

2. 实现

结果:

image-20250127144242881
源码如下:

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);
}
posted @ 2025-01-19 20:46  Arsun  阅读(41)  评论(0)    收藏  举报