【數據結構】25_靜態單鏈表的實現

單鏈表的一個缺陷

  • 觸發條件ios

    • 長時間使用單鏈表對象頻繁增長和刪除元素
  • 可能的結果編程

    • 堆空間產生內存碎片,致使系統運行緩慢

新的線性表

設計思路

在「單鏈表」的內部增長一片預留的空間,全部的Node對象都在這片空間中動態建立和動態銷燬ide

image.png

靜態單鏈表的繼承層次結構

image.png

靜態單鏈表的實現思路

  • 經過類模板定義靜態單鏈表(StaticLinkList)
  • 在類中定義固定大小的空間(unsigned char[])
  • 重寫 create 和 destroy 函數,改變內存的分配和歸還方式
  • 在 Node 類中重載 operator new,用於在指定內存上建立對象

編程實驗:靜態單鏈表的實現

文件:StaticLinkList.h函數

#ifndef STATICLINKLIST_H
#define STATICLINKLIST_H

#include "LinkList.h"

#include <iostream>

using namespace std;

namespace DTLib
{

template <typename T, int N>
class StaticLinkList : public LinkList<T>
{
public:
    StaticLinkList()  // O(n)
    {
        for (int i=0; i<N; ++i)
        {
            m_used[i] = 0;
        }
    }

    int capacity()  // O(1)
    {
        return N;
    }

protected:
    //typedef typename LinkList<T>::Node Node;
    using Node = typename LinkList<T>::Node;

    struct SNode : public Node
    {
        void *operator new (unsigned int size, void *loc)
        {
            (void)size;

            return loc;
        }
    };

    unsigned char m_space[N * sizeof(SNode)];
    char m_used[N];

    Node *create() override  // O(n)
    {
        SNode *ret = nullptr;

        for (int i=0; i<N; ++i)
        {
            if (m_used[i] == 0)
            {
                ret = reinterpret_cast<SNode*>(m_space) + i;
                ret = new(ret)SNode;
                m_used[i] = 1;
                break;
            }
        }

        return ret;
    }

    void destroy(Node *pn) override  // O(n)
    {
        SNode *space = reinterpret_cast<SNode*>(m_space);
        SNode *psn = dynamic_cast<SNode*>(pn);

        for (int i=0; i<N; ++i)
        {
            if (psn == (space + i))
            {
                m_used[i] = 0;
                pn->~Node();
                break;
            }
        }
    }
};

}

#endif // STATICLINKLIST_H

文件:main.cppspa

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

using namespace std;
using namespace DTLib;

int main()
{
    cout << "main begin" << endl;

    StaticLinkList<int, 5> list;

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

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

    cout << "main end" << endl;

    return 0;
}

輸出:設計

main begin
4
3
2
1
0
main end

答疑

LinkList 中封裝 create 和 destroy 函數的意義是什麼呢?

爲靜態單鏈表(StaticLinkList)的實現準備。
StaticLinkList 與 LinkList 的不一樣僅在於鏈表節點內存分配上的不一樣;所以將僅有的不一樣封裝於父類和子類的虛函數中。3d

小結

  • 順序表與單鏈表相結合後衍生出靜態單鏈表
  • 靜態單鏈表是LinkList的子類,擁有單鏈表的全部操做
  • 靜態單鏈表在預留的空間中建立節點對象
  • 靜態單鏈表適合於頻繁增刪元素的場合(最大元素個數固定)

以上內容整理於狄泰軟件學院系列課程,請你們保護原創!code

相關文章
相關標籤/搜索