C语言 数据结构与算法 线性表

本文详细介绍了使用C语言实现线性表的基本操作,包括初始化、销毁、清空、判断是否为空、获取表长、获取指定位置的元素、比较元素大小、查找元素的位置、查找元素的上一个元素、查找元素的下一个元素、插入元素、删除元素及遍历元素等。通过实际代码演示,帮助读者深入理解线性表的概念与应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据结构中逻辑结构分线性和非线性。

线性表即为线性结构中的一种。

线性表的特性 百度百科解释在此

个人总结为 有始有终,顺序排列,首尾不相连(像火车一样)。

线性表的基本操作如下:

初始化,销毁,重置为空表,判断是否为空,查找表的长度,

查找元素的位置,根据位置查找元素,查找元素的上一个元素,查找元素的下一个元素,

插入元素,删除元素,遍历元素。

下面是顺序存储结构的C实现。(有时间可以尝试下链式存储结构的实现)

31142402_OjYY.png

#include <stdio.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INIT_SIZE 10        //初始化表长度
#define INCREMENT_SIZE 5    //增量

typedef int Status;
typedef int Elemtype;

/*
 * 数据存贮结构
 */
typedef struct
{
    Elemtype *elem;    //存储空间基址
    int length;        //当前长度
    int size;        //当前分配的表长大小
}SqList;

/*
 * 初始化线性表
 */
Status InitList(SqList *L)
{
    L->elem = (Elemtype *) malloc(INIT_SIZE * sizeof(Elemtype));
    if (!L->elem)
    {
        return ERROR;
    }
    L->length = 0;
    L->size = INIT_SIZE;
    return OK;
}

/*
 * 销毁
 */
Status DestroyList(SqList *L)
{
    free(L->elem);
    L->length = 0;
    L->size = 0;
    return OK;
}

/*
 * 清空
 */
Status ClearList(SqList *L)
{
    L->length = 0;
    return OK;
}

/*
 * 是否为空
 */
Status isEmpty(const SqList L)
{
    if (0 == L.length)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

/*
 * 获取表长
 */
Status getLength(const SqList L)
{
    return L.length;
}

/*
 * 获取指定位置的元素
 */
Status GetElem(const SqList L, int i, Elemtype *e)
{
    if (i < 1 || i > L.length)
    {
        return ERROR;
    }
    *e = L.elem[i-1];
    return OK;
}

/*
 * 比较元素大小
 */
Status compare(Elemtype e1, Elemtype e2)
{
    if (e1 == e2)
    {
        return 0;
    }
    else if (e1 < e2)
    {
        return -1;
    }
    else
    {
        return 1;
    }
}

/*
 * 查找元素的位置
 */
Status FindElem(const SqList L, Elemtype e, Status (*compare)(Elemtype, Elemtype))
{
    int i;
    for (i = 0; i < L.length; i++)
    {
        if (!(*compare)(L.elem[i], e))
        {
            return i + 1;
        }
    }
    if (i >= L.length)
    {
        return ERROR;
    }
}

/*
 * 查找当前元素的前一个元素
 */
Status PreElem(const SqList L, Elemtype cur_e, Elemtype *pre_e)
{
    int i;
    for (i = 0; i < L.length; i++)
    {
        if (cur_e == L.elem[i])
        {
            if (i != 0)
            {
                *pre_e = L.elem[i - 1];
            }
            else
            {
                return ERROR;
            }
        }
    }
    if (i >= L.length)
    {
        return ERROR;
    }
}

/*
 * 查找当前元素的下一个元素
 */
Status NextElem(const SqList L, Elemtype cur_e, Elemtype *next_e)
{
    int i;
    for (i = 0; i < L.length; i++)
    {
        if (cur_e == L.elem[i])
        {
            if (i < L.length - 1)
            {
                *next_e = L.elem[i + 1];
                return OK;
            }
            else
            {
                return ERROR;
            }
        }
    }
    if (i >= L.length)
    {
        return ERROR;
    }
}

/*
 * 插入元素
 */
Status InsertElem(SqList *L, int i, Elemtype e)
{
    Elemtype *new;
    if (i < 1 || i > L->length + 1)
    {
        return ERROR;
    }
    if (L->length >= L->size)
    {
        new = (Elemtype*) realloc(L->elem, (L->size + INCREMENT_SIZE) * sizeof(Elemtype));
        if (!new)
        {
            return ERROR;
        }
        L->elem = new;
        L->size += INCREMENT_SIZE;
    }
    Elemtype *p = &L->elem[i - 1];
    Elemtype *q = &L->elem[L->length - 1];
    for (; q >= p; q--)
    {
        *(q + 1) = *q;
    }
    *p = e;
    ++L->length;
    return OK;
}

/*
 * 删除元素
 */
Status DeleteElem(SqList *L, int i, Elemtype *e)
{
    if (i < 1 || i > L->length)
    {
        return ERROR;
    }
    Elemtype *p = &L->elem[i - 1];
    *e = *p;
    for (; p < &L->elem[L->length]; p++)
    {
        *(p) = *(p + 1);
    }
    --L->length;
    return OK;
}

/*
 * 访问元素
 */
void visit(Elemtype e)
{
    printf("%d ", e);
}

/*
 * 遍历表
 */
Status TraverseList(const SqList L, void (*visit)(Elemtype))
{
    int i;
    for(i = 0; i < L.length; i++)
    {
        visit(L.elem[i]);
    }
    return OK;
}

//测试
int main()
{
    SqList L;
    if (InitList(&L))
    {
        Elemtype e;
        printf("init_success\n");
        int i;
        for (i=0; i<10; i++)
        {
             InsertElem(&L, i+1, i);
        }
        printf("length is %d\n", getLength(L));
        if (GetElem(L, 1, &e)) {
        printf("This first element is %d\n", e);
        }
        else
        {
            printf("element id not exist\n");
        }
        printf("The 5 at %d\n", FindElem(L, 5, *compare));
        PreElem(L, 6, &e);
        printf("The 6's previoud element is %d\n",e);
        NextElem(L, 6, &e);
     printf("The 6's next element is %d\n", e);
        DeleteElem(&L, 1, &e);
        printf("delete first element is %d\n",e);
        TraverseList(L, visit);
    if (DestroyList(&L))
    {
        printf("\ndestory_success");
    }
    }
}

  看了几遍 终于通了,对新手来说其中比较难理解的地方就是插入元素 那个操作里的 位移操作 举例如下

list 里原本有 1 2  3 4 5  当需要插入 6 到 第二个位置 需要把 2 3 4 5 都往后移动 但是在上面的代码里移动的是元素地址 从最后一个开始 从高位往地位移动 所以比较难理解。

转载于:https://my.oschina.net/u/2241804/blog/646099

### 线性表的顺序存储 线性表是一种基本的数据结构,其特点是元素之间存在一对一的关系。在线性表中,每个元素都只有一个前驱和一个后继(除了第一个和最后一个元素)。**顺序存储**是实现线性表的一种常见方式。 #### 1. 基本概念 - **顺序存储**:将线性表中的所有元素按它们之间的逻辑关系依次存放在一片连续的内存空间中。通常使用数组来表示这种存储方式。 - **优点**: - 元素可以随机访问,即通过下标直接定位到指定位置的时间复杂度为O(1)。 - 存储密度高,因为不需要额外的空间用于指针等辅助信息。 - **缺点**: - 插入和删除操作效率较低,需要移动大量元素以保持物理地址的连贯性,时间复杂度最坏情况为O(n),其中n为线性表长度。 - 需要预先分配足够的存储空间,可能导致浪费或不足的问题。 #### 2. C语言中的实现 以下是用C语言实现的一个简单示例: ```c #include <stdio.h> #include <stdlib.h> #define MAXSIZE 10 // 定义最大容量 typedef struct { int data[MAXSIZE]; // 数据域,存放实际数据项 int length; // 当前线性表的长度 } SqList; // 初始化空的线性表 void InitList(SqList *L) { L->length = 0; } // 插入新元素 e 到第 i 个位置 (从 1 开始) int ListInsert(SqList *L, int i, int e) { if (i < 1 || i > L->length + 1) return 0; // 检查插入位置是否合法 if (L->length >= MAXSIZE) return 0; // 如果已经满了,则无法再添加新的元素 for(int j = L->length; j >= i ; --j){ L->data[j] = L->data[j-1]; } L->data[i-1] = e; ++L->length; return 1; } // 删除第 i 个位置处的元素,并将其值返回给 e int ListDelete(SqList *L, int i, int* e) { if(i<1||i>L->length) return 0; //检查删除位置是否合法 *e = L->data[i-1]; for(int j=i;j<L->length;++j){ L->data[j-1]=L->data[j]; } --L->length; return 1; } ``` 此代码展示了如何创建、初始化以及对线性表进行基本的操作如插入和删除。需要注意的是,在实际应用中我们还需要考虑动态调整大小等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值