zoukankan      html  css  js  c++  java
  • 线性表的链式存储结构——(2)

    线性表的存储结构有两种:顺序存储和链式存储

    顺序存储:读取数据的时间复杂度为O(1),其实就是数组,但是插入,删除的复杂度略大

    链式存储:•用一组任意的存储单元存储线性表的数据元素,这组存储单元可以存在内存中未被占用的任意位置。

    数据域:存储数据元素信息的域
    指针域:把存储直接后继位置的域
    指针或链:指针域中存储的信息
    结点(Node):数据域和指针域组成数据元素称为存储映像
    单链表:链表的每个结点中只包含一个指针域
     
    •头指针
    –头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。
    –头指针具有标识作用,所以常用头指针冠以链表的名字(指针变量的名字)。
    无论链表是否为空,头指针均不为空
    头指针是链表的必要元素
    •头结点
    –头结点是为了操作的统一和方便而设立的,放在第一个元素的结点之前,其数据域一般无意义(但也可以用来存放链表的长度)。
    –有了头结点,对在第一元素结点前插入结点和删除第一结点起操作与其它结点的操作就统一了。
    –头结点不一定是链表的必须要素。
    (单链表图例)
    (空链表图例,头结点可以没有)
    C语言中可以用结构指针来描述单链表:
    typedef struct Node
    {
        ElemType data;      // 数据域
        struct Node* Next;  // 指针域
    } Node;
    typedef struct Node* LinkList;

     GetElem( LinkList L, int i, ElemType *e ):读取链表中的元素

    Status GetElem( LinkList L, int i, ElemType *e )
    {
        LinkList p;  
        int j = 1;
        p = L -> next;  //L为头结点,p为第一个结点 
        if ( !p || i < 1 )    //若头结点指向的为空,或者i非法
        {
            return Error
        }
        while( p && j < i)      //当未到达链表尾端,和还未找到第i个结点
        {
            p = p -> next;
            ++j;
        }                //假设i = 3,若找到,则此时p就是第三个结点
        if ( !p || j > i)      
    //当到达链表尾端能未找到第i个结点,
    也就是i大于链表的长度啦,但是这个是链式存储,似乎没有L.length这个属性,只能判断指针是否为null啦// {
    return Error }                  *e = p->data return *e }

     插入和删除的图示:

    InsertElem( LinkList L, int i, ElemType *e )

    Status InsertElem( LinkList *L, int i, ElemType *e )
    {
        LinkList p,s;
        int j = 1;
        p = *L ;     //p为头结点
        if ( !p || i < 1 )
        {
            return Error
        }
        while( p && j < i)     //找到第i个结点     
        {
            p = p -> next;
            ++j;
        }              //还是假设i= 3,若找到,则此时p是第二个结点
        if ( !p||j > i )
        {
            return Error
        }
        s = (LinkList)malloc(sizeof(Node));    //生成一个新的结点
        s -> data = e;
        s -> next = p -> next;·    //使新结点指向原来第二个结点指向的结点
        p -> next = s;        //使第二个结点指向新结点,则此时,新结点已变成第三个结点
        return OK;
    }

    DeleteElem( LinkList L, int i, ElemType *e)

    Status DeleteElem( LinkList *L, int i, ElemType *e)
    {
        LinkList p;
        int j = 1;
        p = *L ;
        if ( !p || i < 1 )
        {
            return Error
        }
        while( p && j < i)        
        {
            p = p -> next;
            ++j;
        }
        if ( !p )
        {
            return Error
        }
        q = p -> next;
        p -> next = q -> next ;  //或者直接:p->next = p->next->next;
        e = p -> data 
        free(q);
        return OK
    }
    总结:对于插入或删除数据,若数据都是一个的话,顺序存储和单链表复杂度都是,O(n)。顺序存储需要移动n-i个位置,单链表需要查找第i个数据的地址。
    但是如果,需要插入和删除j个数据时,顺序存储复杂度是每次都是O(n),但单链表就只有第一次是O(n),以后都是O(1)(当然前提是连续的插入,如果断断续续的插入,优势就不明显啦。。。对于大量数据的处理,考虑到日后代码的维护,数据的存储肯定是用单链表啦。。)
     
     
     
  • 相关阅读:
    redhat6.4 数据包无法到达
    hibernate-Table 'XXX.XXX' doesn't exist
    LeetCode 之 TwoSum
    vim 中的常用编辑
    linux sed 批量替换多个文件中的字符串
    RedHat 6.4企业版利用iso镜像做本地yum源
    win7 vmware虚拟机上网设置
    virtualbox ubuntu下ssh连接
    Source Insight 插件
    非递归排序
  • 原文地址:https://www.cnblogs.com/shixiaomiao/p/3986603.html
Copyright © 2011-2022 走看看