数据结构【第二天】:线性表(一)

线性表

线性表:0个或多个数据元素的有限序列,记{a1,a2,...,ai-1,ai,...an}

长度为n,为0记为空表

线性表应该具有的操作:

ADT List

Data

    {a1,a2,...,an},每个元素类型为DataType,除第一个元素外,每一个元素有且只有一个直接前驱元素,除最后一个元素外有且只有一个直接后继元素。

Operation

    InitList(*L);    初始化操作,建立一个空的线性表L

    ListEmpty(L);    若线性表为空,返回true,否则返回false

    ClearList(*L);    将线性表清空

    GetElem(L,i,*e);    将线性表L中的第i个位置元素返回给e

    LocateElem(L,e);    在线性表中查找与e值相等的值,若查找成功返回序号,若失败,返回0

    ListInsert(*L,i,e);    在线性表L中第i个位置插入元素e

    ListDelete(*L,i,*e);    删除线性表中第i个位置元素,并用e返回其值

    ListLength(L);    返回线性表L的元素个数

endADT 


线性表的顺序存储结构

用一段地址连续的存储单元依次存储线性表的数据元素

在C/C++中表示为数组

*注意区分数组长度与线性表长度,前者指开辟的存储空间的大小,基本不变;后者指表中元素数据的个数,随着插入和删除是不断变化的。

主要优点:可快速存取表中任意位置的元素

主要缺点:插入和删除需要移动大量的元素


线性表的链式存储结构

节点 = 数据域+指针域

若节点只包含一个指针域,即只知后者,则叫做单链表

头结点:在第一个存储数据的节点之前设置一个头结点,用于存储长度等附加信息,但是并不是必须的;

头指针:指向链表中第一个节点的存储位置,若有头结点,则指向头结点,若无头结点,则指向第一个数据节点,该指针是必须的;

最后一个节点的指针域指向空。

*分辨头节点头指针第一个数据节点最后一个数据节点(笔者自己称为尾节点)以及尾指针等概念;

单链表

节点构造:

typedef struct Node
{
    ElemType data;
    struct Node *next;
}Node;
typedef struct Node *LinkList;

元素读取(读取第i个元素数据):

Status GetElem(LinkList L,int i,ElemType *e)
{
    int j;
    LinkList p;    //声明指针
    p = L->next;   //L为头指针,p指向头节点下一个,即第一个数据 
    j = 1          //j为计数器,当前p指向第一个数据
    while(p&&j<i)    //p不为空且计数j没超过i
    {
        p = p->next;    //指向下一个节点
        ++j;    //计数++
        
    }
    if(!p||j>i)
        return error;    //返回错误,即第i个数据不存在
    *e = p->data;    //给e赋值
    return ok;
}

单链表插入(插入到第i个数据之前)

Status ListInsert(LinkList *L,int i,ElemType e)
{
    int j;
    LinkList p,s;    //定义两个节点指针
    p = *L;          //p指向头指针,注意读取时的代码是指向第一个数据
    j = 1;           //计数 
    while(p&&j<i)    //p非空且计数少于i
    {
        p = p->next;
        ++j;
    }                //上述while结束,此时p指向第i-1个节点
    if(!p||j>i)      //没有第i个节点
        return error;
    s = (LinkList)malloc(sizeof(Node));    //动态生成新节点
    s->data = e;                      //插入节点数据部分赋值
    s-next = p->next;                 //插入节点指针部分指向第i个节点
    p->next = s;                      //第i-1节点指针部分指向插入节点s
    return ok;
}

单链表删除(删除第i个数据)

Status ListInsert(LinkList *L,int i,ElemType *e)
{
    int j;
    LinkList p,q;    //定义两个节点指针
    p = *L;          //p指向头指针,注意读取时的代码是指向第一个数据
    j = 1;           //计数 
    while(p->next&&j<i)    //p->next非空且计数少于i,注意此处与插入不同
    {
        p = p->next;
        ++j;
    }                //上述while结束,此时p指向第i-1个节点
    if(!p||j>i)      //没有第i个节点
        return error;
    q = p->next;    //q记录第i个节点
    p->next = q->next;    //将p节点(第i-1)的指针部分指向第i+1个节点
    *e = q->data;        //将第i个节点的数据给e
    free(q);             //释放q节点占用的内存
    return ok;
}

整表创建(头插入)

void CreatListHead(LinkList *L,int n)
{
    LinkList p;        //创建节点
    int i;
    srand(time(0));
    *L = (LinkList)malloc(sizeof(Node));    //创建头节点、头指针
    (*L)->next = NULL;                      //头节点指向空,即空表
    for(i=0;i<n;i++)    //创建n个节点
    {
        p = (LinkList)malloc(sizeof(Node));    //创建节点
        p->data = rand()%100+1;                //节点数据部分赋值
        p->next = (*L)->next;                  //节点插入到头结点和第一个数据之间
        (*L)->next = p;                        
    }
}

整表创建(尾插入)

void CreatListHead(LinkList *L,int n)
{
    LinkList p,r;        //创建节点
    int i;
    srand(time(0));
    *L = (LinkList)malloc(sizeof(Node));    //创建头节点、头指针
    r = *L;                                 //*r指向尾部的节点
    for(i=0;i<n;i++)                        //创建n个元素
    {
        p = (LinkList)malloc(sizeof(Node));    //创建节点
        p->data = rand()%100+1;                //节点数据部分赋值
        r->next = p;                  //旧尾部的指针部分指向新节点
        r = p;                        //更新尾部
    }
    r->next = NULL;                   //链表结束,尾部指向空
}

整表删除

Status ClearList(LinkList *L)
{
    LinkList p,q;
    p = (*L) -> next;        //p指向第一个数据节点
    while(p)                //p非空
    {
        q = p -> next;        //q为p下一个节点
        free(p);              //释放p;
        p = q;                //跟新p为第一个节点
    }
    (*L) -> next = NULL;       //头节点指针指向空
    return ok;
}

单链表与顺序存储结构比较

主要优势:插入与删除更方便;不需要固定分配空间,元素个数也不受限制。

主要缺点:查找的复杂度增加到了O(n)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值