顺序表操作

顺序表操作

/*
    适用于标准C, 静态数组版本(这不是static的意思,而是data[]这种写法)
    SeqList.c
    V1.0
    2019.9.9 wangx
    后面的函数作为作业,让同学们去完成!
*/
#include <stdio.h>
#include <stdlib.h>
#define INIT_SIZE 10000 // 实际工业编程中,这个数字会很大!!

typedef struct
{
    // 因为线性顺序表很大(10000只是教学范例),所以下面所有函数在传参时,如果要传表,都建议传指针,直接针对原件进行操作!不建议传结构体变量(容易会把栈区撑爆)
    // 如果是int *pdata; 这样的写法,则pdata只有4个字节,SeqList结构体变量的空间量大大缩小,就会方便很多,但就变成动态数组了(需要在堆区中开辟空间来存储数据)
    int data[INIT_SIZE]; // 10000个元素,40000个字节。
    int length;          // 4个字节
    int listsize;        // 4个字节
} SeqList;

SeqList InitList()
{
    SeqList tt;
    tt.length = 0;
    tt.listsize = INIT_SIZE;
    // tt.data[3] = ;
    return tt; // 把局部的结构体变量tt的内容整体赋值给函数的接收者,tt内含的数组也整体复制了过去。tt在return后被释放。
}

// 因为顺序表是通过传参进来的,其内部数据在插入操作中会被修改,所以此处形参应该设为指针,去操作main函数中对应的实参list1
// 如果第一个参数设为SeqList,而不是SeqList *,则pL就不再是一个指针,而变成了栈区中的一个结构体变量(408个字节),对它的修改操作根本不会影响到list1
// 本例中,i表示下标位置,从0开始编号的。如果要从1开始编号,下面代码都需要微调
int listInsert(SeqList *pL, int i, int value)
{
    int j;
    // 3.参数校验
    if (i > pL->length || i < 0 || pL == NULL)
        return -1; // 参数有误,返回错误码 -1
    // 4.考虑极端情况
    if (pL->length >= pL->listsize)
        return -2; // 表满,出现上溢,返回错误码 -2 (静态数组版本的线性表,没法进行表空间扩充,这一点和用指针来表示的动态数组版本的不一样)
    // 5.到现在才处理常规套路
    for (j = pL->length; j > i; j--)
        pL->data[j] = pL->data[j - 1];

    pL->data[j] = value;
    pL->length++; // 这句千万别忘了!
    return 0;
}

// 本函数虽然没有改变线性表实参,但是因为线性表实在是太大了,为节省栈空间,提高效率,建议用指针来操作原件,而不是操作栈区中的结构体变量复印件
int getValue(SeqList *pL, int i)
{
    // 3. 参数校验(从零开始)
    if (i < 0 || i > pL->length - 1 || pL == NULL)
        return -1;
    // 4. 考虑极端情况,本函数没有极端情况,不写
    // 5. 常规套路,顺序存储结构可以直接提取第i个元素,很简单,就一句话
    return pL->data[i];
}

void printAll(SeqList *pL)
{
    int i;
    if (pL == NULL)
        return;
    for (i = 0; i < pL->length; i++)
        printf("%d  ", getValue(pL, i));
    return;
}

// 删除值为x的元素
int delet_special(SeqList *pL, int value)
{

    int j, k = 0;
    while (pL->data[k] != value || k > pL->length) //遍历表找对应值且k值合法的参数校验
    {
        k++;
    }
    if (k < pL->length) // k<pL->length,则找到了值
    {
        for (j = k; j < pL->length; j++) //从k位置开始将后买你的数据往前挪
            pL->data[j] = pL->data[j + 1];
        pL->length--; //挪完后,表的长度缩减1
        return 0;
    }
    else
        return -1;
}
// 删除第i个元素(i从0开始编号)
void delet_index_value(SeqList *pL, int index)
{
    int j;
    if (index > pL->length || index < 0) //参数校验
    {
        exit(0);
    }
    else
    {
        for (j = index; j < pL->length; j++) //找到下标,将index后的数据依次往前挪
            pL->data[j] = pL->data[j + 1];
        pL->length--;
    }
}

// 返回表长
int return_the_length(SeqList *pL)
{
    return pL->length;
}
// 合并无序表(因为静态数组版本不能扩充空间,所以需要先检验AB两表有效数据个数,不能超过INIT_SIZE,否则只能罢工)
void merge(SeqList *p1, SeqList *p2)
{
    int i, j;
    int temp;
    if ((p1->length) + (p2->length) > (p1->listsize))
    {
        return;
    }
    else
    {
        temp = p1->length;
        p1->length += p2->length;

        for (i = temp; i < (p1->length); i++)
        {
            for (j = 0; j < ((p1->length) - i); j++)
                p1->data[i] = p2->data[j];
        }
    }
}
int main()
{
    SeqList list1, list2;
    SeqList *pList = &list1;
    list1 = InitList();
    list2 = InitList();
    listInsert(&list2, 0, 10);
    listInsert(&list1, 0, 10);
    listInsert(&list1, 1, 20);
    listInsert(pList, 2, 40); // 第一个参数,这种写法也是完全可以的!
    listInsert(&list1, 2, 30);
    listInsert(&list1, 0, 5);             // 头插
    listInsert(&list1, list1.length, 50); // 尾插
    puts("List1");
    printAll(&list1);
    delet_special(pList, 10); // 删除值为x的元素
    puts("\n删除值为10的元素");
    printAll(&list1);
    puts("");
    puts("删除第2个元素 i从0开始编号");
    delet_index_value(pList, 2); //删除第i个元素(i从0开始编号)
    printAll(&list1);
    puts("");
    puts("List2");
    printAll(&list2);
    puts("\n合并后");
    merge(&list1, &list2);
    printAll(&list1);
    printf("\n表长为%d\n", return_the_length(&list1));
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值