zoukankan      html  css  js  c++  java
  • 线性表顺序存储结构

    先看看官方是怎么定义线性表的吧!

    线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。
    线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储),但是把最后一个数据元素的尾指针指向了首位结点)。
    各位看完了吧,接下来该轮到我来讲解了!
    其实线性表也可以称之为序列表,因为他是有序的,
    所以可以用C语言里的一维数组来实现,线性表中首元素无前驱,末元素无后继,除首尾元素外,中间的其他元素既有前驱也有后继,什么是前驱是什么后继呢?
    就拿我对象的所工作的幼儿园小朋友们来举例子吧!
    在课外活动中,老师让每个小朋友们手拉着旁边小朋友们的手形成一列,最靠左的小朋友们,他的右手没有人拉他,即没有前驱,靠最右边的小朋友他的左手没人拉,即无后继,而中间的小朋友们的左右手都有其他小朋友们拉着,即有前驱和后继。
    并且队列中小朋友们的人数不能大于全班所有小朋友的人数,也就是所谓的队列的长短要小于整个数组的大小
    那么接下来咱们实现一下小朋友们手拉手形成的线性表吧!
    首先咱们得先创造小朋友们,有人说小朋友都是爹妈生的,你咋造!你可以把我比作女娲吧,~哈哈!因为小朋友们成长离不开所需的营养元素,咱们先看看需要什么营养元素吧!
    #include "stdio.h"
    #include "stdlib.h"
    #include "io.h"
    #include "math.h"
    #include "time.h"
    
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    
    #define MAXSIZE 20 /* 存储空间初始分配量 */
    
    typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
    typedef int Elemtype;  /* ElemType类型根据实际情况而定,这里假设为int 

    看完了小朋友们所需的生长元素,接下来就开创造小朋友们吧!

    typedef struct
    {
        ElemType data[MAXSIZE]; /* 数组,存储数据元素 */
        int length;             /* 线性表当前长度 */
    }SqList;

    小朋友们被造好之后,咱们为了让小朋友们站的更整齐些,于是画一行正方形的位置块,让每个小朋友们手拉着手站在各自的块里,像下面这样

    /* 初始化顺序线性表 */
    Status InitList(SqList *L)
    {
        L->length = 0;
        return OK;
    }

     画完格子后,怕有些淘气的小朋友们站在格子里玩耍,咱们得先看看格子里是不是空的

    Status ListEmpty(SqList L)
    {
        if (L.length == 0)
        {
            return TRUE;
        }
        else{
            return FALSE;
        }
    }

    如果此时有小朋友们站在格子里,咱们得告诉他,让他离开,使格子里面没有小朋友

    /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
    Status ClearList(SqList *L)
    {
        L->length = 0;
        return OK;
    }

    现在有新来的小朋友加入我们,那么咱们让新来的小朋友手去她喜欢的格子里,然后开始做游戏了

    Status ListInsert(SqList *L, int i, ElemType e)
    {
        int k;
        if (L->length == MAXSIZE) /* 顺序线性表已经满 */
        {
            return ERROR;
        }
        if (i<1 || i>L->length+1)/* 当i比第一位置小或者比最后一位置后一位置还要大时 */
        {
            return ERROR;
        }
        if (i <= L->length)
        {
            for (k = L->length - 1; k >= i - 1; k--)
            {
                L->data[k + 1] = L->data[k];
            }
        }
        L->data[i - 1] = e;
        L->length++;
        return OK;
    }

    但是有的小朋友们不乖,骚扰左右的小朋友,因此,需要让他出队面壁思过去

    /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
    /* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
    Status ListDelete(SqList *L, int i, ElemType *e)
    {
        int k;
        if (L->length = 0)   /* 线性表为空 */
        {
            return ERROR;
        }
        if (i<1 || i>L->length - 1) /* 删除位置不正确 */
        {
            return ERROR;
        }
        *e = L->data[i];
        if (i < L->length) /* 如果删除不是最后位置 */
        {
            for (k = i; k < L->length; k++)  /* 将删除位置后继元素前移 */
            {
                L->data[k-1] = L->data[k];
            }
        }
        L->length--;
        return OK;
    }

    在整个队列里面,花花小朋友表现得最好,咱们数数花花在哪个位置吧

    int LocateElem(SqList L, ElemType e)
    {
        int i=0;
        if (i >= L.length || L.length==0)
        {
            return 0;
        }
        for (i = 0; i < L.length; i++)
        {
            if (L.data[i] == e)
            {
                break;
            }
        }
        return i + 1;
    }

    咱们再来查查哪个小朋友站在第i个位置啊

    Status GetElem(SqList L, int i, ElemType *e)
    {
        if (i < 1 || i > L.length || L.length == 0)
        {
            return ERROR;
        }
        *e = L.data[i-1];
        return OK;
    }

    小朋友们表现得都很不错,咱们现在来看看一共有多少个小朋友参加这个游戏

    int ListLength(SqList L)
    {
        return L.length;
    }

    小朋友们这个游戏好不好玩啊!好玩的话,请大家记住好自己的位置,咱们下次再继续玩!

    Status ListTraverse(SqList L)
    {
        int i;
        for (i = 0; i < L.length; i++)
        {
            printf("%d", L.data[i]);
        }
        printf("
    ");
        return OK;
    }

    好了,咱们开始测试一下,咱们的代码吧!

    void unionL(SqList *La, SqList Lb)
    {
        int La_len, Lb_len, i;
        ElemType e;
        La_len = ListLength(*La);
        Lb_len = ListLength(Lb);
        for (i = 1; i <= Lb_len; i++)
        {
            GetElem(Lb, i, &e);
            if (!LocateElem(*La, e))
                ListInsert(La, ++La_len, e);
        }
    }
    
    int main()
    {
        SqList L;
        SqList Lb;
    
        ElemType e;
        Status i;
        int j, k;
        i = InitList(&L);
        printf("初始化L后:L.length=%d
    ", L.length);
        for (j = 1; j <= 5; j++)
            i = ListInsert(&L, 1, j);
        printf("在L的表头依次插入1~5后:L.data=");
        ListTraverse(L);
    
        printf("L.length=%d 
    ", L.length);
        i = ListEmpty(L);
        printf("L是否空:i=%d(1:是 0:否)
    ", i);
    
        i = ClearList(&L);
        printf("清空L后:L.length=%d
    ", L.length);
        i = ListEmpty(L);
        printf("L是否空:i=%d(1:是 0:否)
    ", i);
    
        for (j = 1; j <= 10; j++)
            ListInsert(&L, j, j);
        printf("在L的表尾依次插入1~10后:L.data=");
        ListTraverse(L);
    
        printf("L.length=%d 
    ", L.length);
    
        ListInsert(&L, 1, 0);
        printf("在L的表头插入0后:L.data=");
        ListTraverse(L);
        printf("L.length=%d 
    ", L.length);
    
        GetElem(L, 5, &e);
        printf("第5个元素的值为:%d
    ", e);
        for (j = 3; j <= 4; j++)
        {
            k = LocateElem(L, j);
            if (k)
                printf("第%d个元素的值为%d
    ", k, j);
            else
                printf("没有值为%d的元素
    ", j);
        }
    
    
        k = ListLength(L); /* k为表长 */
        for (j = k + 1; j >= k; j--)
        {
            i = ListDelete(&L, j, &e); /* 删除第j个数据 */
            if (i == ERROR)
                printf("删除第%d个数据失败
    ", j);
            else
                printf("删除第%d个的元素值为:%d
    ", j, e);
        }
        printf("依次输出L的元素:");
        ListTraverse(L);
    
        j = 5;
        ListDelete(&L, j, &e); /* 删除第5个数据 */
        printf("删除第%d个的元素值为:%d
    ", j, e);
    
        printf("依次输出L的元素:");
        ListTraverse(L);
    
        //构造一个有10个数的Lb
        i = InitList(&Lb);
        for (j = 6; j <= 15; j++)
            i = ListInsert(&Lb, 1, j);
    
        unionL(&L, Lb);
    
        printf("依次输出合并了Lb的L的元素:");
        ListTraverse(L);
    
    
        getchar();
        return 0;
    }

     总结:

    1、首先关于表里功能函数的形参问题,有的形参被设定为 SqList *L,而有的为SqList L,这个得看需对整个列表做什么操作了,如果需要对整个列表进行初始化、插入、删除、设为空,则形参应为SqList *L,若对列表操作仅仅是查找,打印,不影响整个列表的框架操作,形参则设置为SqList L。

    2、关于L->length和L.length的问题

    若功能函数的形参为SqList *L,则可以进行L->length操作,若功能函数的形参为SqList L,则可以进行L.length操作。

    首先L->length是对整个序列中元素的序号进行操作的,若L->length=0;则表示将序列清空 ,若L->length==n,则序列里有n个元素。

    而L.length则表示的是序列最后一个元素的序号,若L.length==0,则表示序列为空表,若L.length==n,同样也表示为序列里有你个元素

  • 相关阅读:
    Nginx(一)——介绍及安装配置
    Keepalived(二)
    H3C 交换机限速和添加Vlan
    The difference between su and su-
    CentOS7 修改 ssh 文件总结
    华为eNSP模拟器学习(一)
    如何使用Open Live Writer
    Ubuntu 开启远程ssh服务
    CentOS7 禁用firewall防火墙 启用iptables 步骤
    CentOS 7 精简版安装后联网问题
  • 原文地址:https://www.cnblogs.com/zhuifeng-mayi/p/10802462.html
Copyright © 2011-2022 走看看