91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

單鏈表的優化(十三)

發布時間:2020-09-13 20:47:09 來源:網絡 閱讀:760 作者:上帝之子521 欄目:軟件技術

        我們在之前實現了單鏈表,那么我們如何遍歷單鏈表中的每一個數據元素呢?肯定直接一個 for 循環就可以搞定啊,我們來看看當前基于我們實現的單鏈表遍歷的方法,main.cpp 如下

#include <iostream>
#include "LinkList.h"

using namespace std;
using namespace DTLib;

int main()
{
    LinkList<int> list;

    for(int i=0; i<5; i++)      // O(1)
    {
        list.insert(0, i);
    }

    for(int i=0; i<list.length(); i++) // O(n)
    {
        cout << list.get(i) << endl;
    }

    return 0;
}

        我們來看看輸出結果,看看是不是遍歷呢

單鏈表的優化(十三)

        結果是正確的,我們來分析下上面的測試代碼的效率。第一個 for 循環,因為每次都是在 0 位置處插入數據元素,因此它的時間復雜度是 O(1);而第二個 for 循環,因為它要全部循環一遍,因此它的時間復雜度為 O(n)。我們就奇怪了,明明同樣是兩個 for 循環,效率竟然不相同。不能以線性的時間復雜度完成單鏈表的遍歷,那么此時新的需求就產生了:為單鏈表提供新的方法,在線性時間內完成遍歷。

        下來說說設計思路,利用游標的思想:

        1、在單鏈表的內部定義一個游標(Node* m_current);

        2、遍歷開始前將游標指向位置為 0 的數據元素;

        3、獲取游標指向的數據元素;

        4、通過結點中的 next 指針移動游標。


        提供一組遍歷相關的函數,以線性的時間復雜度完成遍歷鏈表,如下

單鏈表的優化(十三)

        遍歷函數原型設計如下:

        bool move(int i, int step = 1);

        bool end();

        T current();

        bool next();


        下來我們來看看優化后的 LinkList.h 是怎樣的,如下


LinkList.h 源碼

#ifndef LINKLIST_H
#define LINKLIST_H

#include "List.h"
#include "Exception.h"

namespace DTLib
{

template < typename T >
class LinkList : public List<T>
{
protected:
    struct Node : public Object
    {
        T value;
        Node* next;
    };

    mutable struct : public Object
    {
        char reserved[sizeof(T)];
        Node* next;
    } m_header;

    int m_length;
    int m_step;
    Node* m_current;

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

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

        return ret;
    }
public:
    LinkList()
    {
        m_header.next = NULL;
        m_length = 0;
        m_step = 1;
        m_current = NULL;
    }
    bool insert(const T& e)
    {
        return insert(m_length, e);
    }

    bool insert(int i, const T& e)
    {
        bool ret = ((0 <= i) && (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 memory to insert new element ...");
            }
        }
    }

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

        if( ret )
        {
            Node* current = position(i);
            Node* toDel = current->next;

            current->next = toDel->next;

            delete toDel;

            m_length--;
        }

        return ret;
    }

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

        if( ret )
        {
            position(i)->next->value = e;
        }

        return ret;
    }

    T get(int i) const
    {
        T ret;

        if( get(i, ret) )
        {
            return ret;
        }
        else
        {
            THROW_EXCEPTION(IndexOutOfBoundsException, "Invaild parameter i to get element ...");
        }
    }

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

        if( ret )
        {
            e = position(i)->next->value;
        }

        return ret;
    }

    int find(const T& e) const
    {
        int ret = -1;
        int i = 0;
        Node* node = m_header.next;

        while( node )
        {
            if( node->value == e )
            {
                ret = i;
                break;
            }
            else
            {
                node = node->next;
                i++;
            }
        }

        return ret;
    }

    int length() const
    {
        return m_length;
    }

    void clear()
    {
        while( m_header.next )
        {
            Node* toDel = m_header.next;

            m_header.next = toDel->next;

            delete toDel;
        }

        m_length = 0;
    }

    bool move(int i, int step = 1)
    {
        bool ret = (0 <= i) && (i < m_length) && (step > 0);

        if( ret )
        {
            m_current = position(i)->next;
            m_step = step;
        }

        return ret;
    }

    bool end()
    {
        return (m_current == NULL);
    }

    T current()
    {
        if( !end() )
        {
            return m_current->value;
        }
        else
        {
            THROW_EXCEPTION(INvalidOPerationException, "No value at current position ...");
        }
    }

    bool next()
    {
        int i = 0;

        while( (i < m_step) && !end() )
        {
            m_current = m_current->next;
            i++;
        }

        return (i == m_step);
    }

    ~LinkList()
    {
        clear();
    }
};

}

#endif // LINKLIST_H

 

main.cpp 源碼

#include <iostream>
#include "LinkList.h"

using namespace std;
using namespace DTLib;

int main()
{
    LinkList<int> list;

    for(int i=0; i<5; i++)      // O(1)
    {
        list.insert(0, i);
    }

    for(list.move(0); !list.end(); list.next()) // O(1)
    {
        cout << list.current() << endl;
    }

    return 0;
}

        我們來看看編譯結果

單鏈表的優化(十三)

        我們看到結果還是正確的,證明我們上面代碼的編寫是沒有錯誤的。我們再來分析下,它每次移動,移動后 current 指針就停在那塊,等到下次移動的時候還是從這塊開始移動。也就是說,每次遍歷的時候,它只需要遍歷一次就可以輸出結果了,這樣的話它遍歷的時間復雜度就為 O(1) 了。我們再來將 new 和 delete 操作封裝下,方便后面的使用,具體封裝如下

virtual Node* create()    
{
    return new Node();
}

virtual void destroy (Node* pn)
{
    delete pn;
}

        然后將下面的 new 和 delete 操作全部換成 create 和 destory 函數。我們來試下將 main.cpp 測試代碼中移動的 step 改為 2,那么它便輸出的是偶數了。我們來看看結果

單鏈表的優化(十三)

        確實是輸出的只有偶數。那么我們移動的 step 為 10 呢?那它就應該只輸出 4 了,我們再來看看結果單鏈表的優化(十三)

        現在我們的 LinkList 類已經近乎完美了,優化后的效率遍歷的時候極大的提高了。通過今天對 LinkList 優化的學習,總結如下:1、單鏈表的遍歷需要在線性時間內完成;2、在單鏈表內部定義游標變量,通過游標變量提高效率;3、遍歷相關的成員函數是相互依賴,相互配合的關系;4、封裝結點的申請和刪除操作更有利于增強擴展性。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

汨罗市| 张家川| 景宁| 合阳县| 新化县| 通许县| 通海县| 株洲市| 黔江区| 阜宁县| 稻城县| 德昌县| 比如县| 博罗县| 陈巴尔虎旗| 肃宁县| 临桂县| 温宿县| 来凤县| 甘肃省| 济南市| 锦屏县| 凯里市| 柯坪县| 城市| 斗六市| 吉林市| 遂昌县| 封开县| 渝北区| 阳朔县| 理塘县| 德保县| 淅川县| 荔浦县| 吉安县| 庆云县| 安泽县| 裕民县| 巴中市| 迭部县|