数据结构 第25课 静态单链表的实现------------------狄泰软件学院

文章目录

引用文章: 可做参考

StaticLinkList.h

#ifndef STATICLINKLIST_H
#define STATICLINKLIST_H

#include "LinkList.h"


/*

  父类有父类的实现版本,子类有子类的实现版本------多态的应用

  顺序表有预留空间(但是效率有问题), 单链表没有预留空间(直接在堆空间创建节点), 于是想到两者可结合一下;
  最后得到一种叫做  静态单链表的新的线性表数据结构


  单链表:
        创建很多的节点,归还空间后留下内存碎片,当需要一整块内存的时候,系统将进行碎片整理,然而这需要时间。
  其本质: 堆空间是公用的,每个人都可以用,为了解决这个问题,静态单链表就诞生了。



  静态单链表(思路):
          预留一段内存出来,可以是任意一段合法的内存(不管这段内存的出处是哪里,只要连续就可以了),
  插入 --> 数据元素的时候,在这段空间中查看有没有空位置,然后创建Node对象,
  删除 --> 的时候,就在这片空间调用析构函数,然后将这片内存空间标记为可用,就可以了;

  静态单链表 和 单链表:
          除了内存分配不同,其它完全一样,因仅需要改两个函数就行,creat()   destroy(Node *pn),
          两个函数操作的是单独的一块内存。


*/



namespace DTLib
{
    
    

template < typename T, int N >
class StaticLinkList : public LinkList<T>
{
    
    
protected:
    typedef typename LinkList<T>::Node Node;    // typedef 简化一个类型,给一个类型新的名字 Node

    // 父类的Node和泛指类型和泛指类型牵扯上了关系,此处不可用,故而需要重新定义
    // LinkList<T>::Node 编译器不知道这是类型还是静态成员变量,需要关键字typename出场
    //unsigned char m_space[sizeof(typename LinkList<T>::Node) * N];    // 定义这片内存空间

    unsigned char m_space[sizeof(Node) * N];  // 定义这片内存空间
    int m_used[N];    // 标记数组


     // --> 重载 new 操作符
    struct SNode : public Node
    {
    
    
        void* operator new(unsigned int size, void* loc)  // 要来两个参数,我们的目的是:在指定的内存上调用构造函数
        {
    
    
            (void)size;   // C语言中的暴力处理方式
            return loc;   // 直接返回内存地址(调用构造函数的内存地址)
        }

    };

    SNode* creat()
    {
    
    
        SNode* ret = NULL;
        for(int i=0; i<N; i++)    // 遍历这片空间,看那些是可用的, 每个单元都看看是否被使用了
        {
    
    
            if(!m_used[i])        // 如果i这个单元没有被使用,就可以分配这个单元了
            {
    
    
                ret = reinterpret_cast<SNode*>(m_space) + i;  // 做强制类型转换 和 指针运算 (仅分配内存)
                // 仅仅这么写是有问题的,不会调用Node构造函数
                // 那么问题来了:   分配好内存之后,我们还要在指定的内存上调用构造函数,如何做?
                // --> 重载 new 操作符


                /*  分析:   父类中 Node 的定义
                struct Node : public Object
                {
                    T value;         //  泛指类型的value有可能是个对象,是用户自定义类类型的对象,必然牵扯构造问题
                    Node* next;      //  value 构造必然涉及到 Node 构造函数调用
                };
                */



                ret = new(ret)SNode();  // 在指定的空间中,调用构造函数的代码, () 表示你想在哪一个内存空间上调用构造函数

                                        // 成功解决问题,构造函数也被调用;



                m_used[i] = 1;          // 标记一下,当前的这片内存单元已经分配出去了
                break;
            }
        }
        return ret;
    }

    void destroy(Node *pn)
    {
    
    
        SNode* space = reinterpret_cast<SNode*>(m_space);  // 要做指针运算,所以要做强制类型转换
        SNode* pst = dynamic_cast<SNode*>(pn);             // 从父类指针转换到子类指针
        for(int i=0; i<N; i++)      // 查看需要归还的空间是哪一个
        {
    
    
            if(pst == (space + i))  // 当pst 等于(space + i) 的地址时, i 空间需要归还
            {
    
    
                m_used[i] = 0;      // 标记当前内存单元可用
                pst->~SNode();      // 析构

            }
        }
    }

public:
    StaticLinkList()
    {
    
    
        for(int i=0; i<N; i++)
        {
    
    
            m_used[i] = 0;
        }

    }

    int capacity()
    {
    
    
        return N;
    }

};

}



#endif // STATICLINKLIST_H

main.cpp

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

using namespace std;
using namespace DTLib;


int main()
{
    
    
    StaticLinkList<int, 5> list;

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

    //list.insert(6);   // 所定义的空间只能5个int,create() 无法找到可用空间,就爆掉了
                        // StaticLinkList.h --> create() 返回空指针
                        //  LinkList.h ---> insert()  Node 为空,抛出异常
    
     

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

    try
    {
    
    
        list.insert(1);
    }
    catch (const Exception& obj)
    {
    
    
        cout << obj.message() << endl;
        cout << obj.location() << endl;
    }


    return 0;
}






简直是神奇      ‘

猜你喜欢

转载自blog.csdn.net/dashuu/article/details/115057572