链式存储结构线性表

链式存储结构线性表


顺序表的问题:

1、顺序表的访问和修改的时间复杂度是常数级的,非常快。但是顺序表的插入和删除的缺不好,这两种操作的时间复杂读是O(N),看上去挺好,但是顺序表的插入和删除是通过大量数据的移动形成的。考虑最坏的情况,一个顺序表很长,在第一个位置插入元素,或者删除一个很长的顺序表的第一个元素,需要移动大量的元素,当元素的类型是复杂的类类型时,这种情况就更糟了。

2、顺序表是定长的,如果我们申请的长度不够用时,可以使用动态的顺序表,这样是可以实现,但是,又遇到了上述的问题,需要拷贝很多元素,而且元素类型是复杂的类类型时,就和上述问题差不多了


链表可以完美的解决上述的两点问题。


链表:

线性表中的元素在物理空间上不再是连续的,而在逻辑上是连续的。为了实现在逻辑上是连续的描述,链表中的元素由两部分构成,一部分是数据域,另一部分是指针域。这两部分结合起来,我们称之为结点。这时因为逻辑上的连续,所以依然是一种线性表。


基本概念(单链表):

头结点,数据域不写任何数据,指针域是第一个数据结点的地址,只是起到了一个辅助操作的作用
数据结点:数据域和指针域都用到了,包含了数据和后继结点的地址信息
尾结点:链表中的最后一个结点,指针域为空
尾结点是一个特殊的数据结点,因为它大体上可以提现一个链表的类型。


怎么解决开始提出的两个问题:

    Node* position(int i) const
    {
        Node* ret = reinterpret_cast<Node*>(&m_header);

        for(int p=0; p<i; p++)
        {
            ret = ret->next;
        }
        return ret;
    }


    bool insert(int i, const T& e)
    {
        bool ret = ((i >= 0) && (i <= m_length));

        if( ret )
        {
            Node* node = new Node;
            if(node != NULL)
            {
                Node* current = position(i);

                node->value = e;
                node->next = current->next;
                current->next = node;

                m_length++;
            }
            else
            {
                THROW_EXCEPTION(NoEnoughMemoryException,"No enough memory to insert element!");
            }
        }

        return ret;
    }

这个插入的时间复杂读也是O(N),定义一个指向头结点的指针,循环N次,指针指向了N-1号结点,此时的指针域即是我们想要操作的结点的地址。此时申请一个结点,将我们的数据写入数据域,然后先把申请的结点的指针域指向N号结点的地址,然后再把N-1号几点的指针域修改为我们申请的结点内存,这样就插入了一个元素。插入的顺序一定不能颠倒,我们那样操作,保证了始终是一个完整的链表。这个操作的顺序决定了你能不能构造一个好的链表。可以发现,链表的插入虽然时间复杂读和顺序表相同,但是没有大量元素的移动,只是指针的操作,非常简单方便。

删除也是一样的倒立,都是指针的操作,不涉及元素的大量移动。得到-1号结点的指针后,用一个指针变量得到0号结点的地址,即-1号结点的指针域,然后把-1好的指针域指向+1号的结点地址,这样0号结点就从链表上消失了,但是为了不发生内存泄露,我们此时去释放0号结点地址的内存,因为上述我们已经用变量提前保存了信息,所以不会不知道被移走的结点的地址。

    bool remove(int i)
    {
        bool ret = ((i >= 0) && (i < m_length));

        if( ret )
        {
            Node* current = position(i);

            Node* toDel = current->next;
            current->next = toDel->next;

            delete toDel;

            m_length--;
        }

        return ret;
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值