静态链表(C++实现)——基于数据结构(沈俊版)(初学者食用)

静态链表(C++实现)——基于数据结构(沈俊版)

初学数据结构,不喜勿喷。欢迎大佬们指正!

静态链表是利用数组来模拟存储空间来实现链表的,如果为数组中每一个元素附加一个链接指针(数组下标),就形成静态链表结构。它允许不改变各元素的物理位置,只要重新链接就能改变这些元素的逻辑顺序。由于它是利用数组定义的,在整个运算过程中存储空间的大小不会发生改变,因此称为静态链表。

静态链表(C++)源代码

// StaticLinkList.h
#ifndef STATICLINKLIST_H       //静态链表类模板头文件,仅供学习数据结构参考使用
#define STATICLINKLIST_K
#define MAXSIZE 1000
#include<iostream>
using namespace std;

template <typename T>          //提前声明类模板
class StaticLinkList;

template <typename T>
class Node                 //节点类
{
private:
    T data;                //数据域,存放任意类型的数据
    int next;              //指针域,存放指向下一个节点的指针;每条链链尾元素的next值为-1
    friend class StaticLinkList<T>;  //声明友元,以便访问私有成员
};

template <typename T>
class StaticLinkList         //静态链表类
{
private:                    //静态链表分为两条链(严格上说是在同一片连续的存储空间上同时存放,每条链相邻元素之间逻辑上相连,但物理存储上不一定相连)
    int avail;              //avail作为可利用空间表表(不带头结点的链表)头指针,在无实际静态链表时值为0,即可利用空间表的开始
    int head;               //head作为实际静态链表(带头结点的链表)的头指针,一般置为0
    Node<T> *sll;           //用于存放静态链表的节点数组
    int size;               //记录链表容量
public:
    StaticLinkList();        //默认的构造函数
    StaticLinkList(T v[],int n,int Size=MAXSIZE);     //用连续的一组数构造静态链表
    virtual ~StaticLinkList();
    StaticLinkList(const StaticLinkList<T> &List);
    StaticLinkList<T> & operator=(const StaticLinkList<T> &List);
    void Insert(const T &e,const int &n);             // 指定逻辑顺序(第n个元素后)插入新元素
    void InsertElem(const T &e);                      // 静态链表表头之前插入新元素
    void FreeList();
    void DeleteElem(const int &n,T &e);
    void SetElem(const int &n,const T &e);
    void Reverse();                                   //实际静态链表逻辑顺序转置,可用空间表不变
    int Search(const T &e) const;                      //查找某个元素在实际静态链表中的逻辑顺序,若匹配失败则返回-1
    int Getlength() const;                           //获得实际静态链表的长度(元素个数)
    bool Full() const;
    bool Empty() const;
    void Output(ostream &out) const;
};

template <typename T>
StaticLinkList<T>::StaticLinkList()
{
    avail = 0;
    head = -1;                         //链表未使用前head=-1
    size = MAXSIZE;
    sll = new Node<T>[MAXSIZE];
    for(int i=0;i<MAXSIZE-1;i++)
        sll[i].next = i+1;
    sll[MAXSIZE-1].next = -1;           //可利用表表尾节点的next域为-1

}

template <typename T>
StaticLinkList<T>::StaticLinkList(T v[],int n,int Size)     //用连续的一组数构造静态链表,未考虑异常处理
{
    head = 0;
    size = Size;
    sll = new Node<T>[Size];
    for(int i=0;i<Size-1;i++)             //初始化所有节点的next域,使得每个节点逻辑上相连
        sll[i].next = i+1;
    sll[Size-1].next = -1;                //表尾节点next域一定为0
    for(int i=1;i<=n;i++)
        sll[i].data = v[i-1];
    sll[n].next = -1;                     //实际静态链表最后一个节点next域表示为-1
    avail = (n+1)>=Size?-1:(n+1);         //判断是否存在可利用表以及avail指针的值
}

template <typename T>
StaticLinkList<T>::~StaticLinkList()
{
    FreeList();
}

template <typename T>
StaticLinkList<T>::StaticLinkList(const StaticLinkList<T> &List)
{
    *this = List;
}

template <typename T>
StaticLinkList<T> & StaticLinkList<T>::operator=(const StaticLinkList<T> &List) //实现深拷贝
{
    if( &List == this )                 //判断是否为自身
        return *this;
    FreeList();
    if(List.Empty())
        return *this;
    sll = new Node<T>[List.size];
    head = List.head;
    avail = List.avail;
    size = List.size;
    for(int i=0;i<size;i++)
        sll[i].next = List.sll[i].next;    //拷贝next域
    int x = List.head;
    while(x!=-1)                           //拷贝实际静态链表的数据域
    {
        sll[x].data = List.sll[x].data;
        x = sll[x].next;                  //类似于动态链表的 p = p-> next语句,该语句可以让x指针指向实际静态链表的下一节点
    }
    return *this;
}

template <typename T>
void StaticLinkList<T>::Insert(const T &e,const int &n)   // 指定逻辑顺序(第n个元素后)插入新元素
{
    if(Full())                              //判断是否表满
    {
        cout<<"链表已满,插入失败!"<<endl;
        return;
    }
    if( !Empty() )                      //当实际静态链表中已有节点时:
    {
       int t = avail,x = head;          //找到并用t取可利用表表头指针avail,并用其指向的节点存放新数据,下面完善指针指向关系
       avail = sll[avail].next;         // avail指向可利用表下一节点
       for(int i=0;i<n;i++)
           x = sll[x].next;             //找到原实际静态链表(逻辑上)第n个节点,其next域应赋值为t
       sll[t].next = sll[x].next;       //新节点的next域指向之前x的next域,实现连接
       sll[x].next = t;
       sll[t].data = e;
    }
    else                               //若此时为未使用的空链表:
    {
        head = 0;
        avail = 2;
        sll[1].data = e;
        sll[1].next = -1;             //直接在sll[1]位置插入数据
    }
}

template <typename T>
void StaticLinkList<T>::InsertElem(const T &e)        // 静态链表表头之前插入新元素
{
    if(Full())
    {
        cout<<"链表已满,插入失败!"<<endl;
        return;
    }
   if( !Empty())
   {
       int t = avail ;
    avail = sll[avail].next;
    sll[t].next = sll[head].next;
    sll[t].data = e;
    sll[head].next = t;
   }
   else
    {
        head = 0;
        avail = 2;
        sll[1].data = e;
        sll[1].next = -1;
    }

}

template <typename T>
void StaticLinkList<T>::FreeList()
{
    head = -1;
    avail = 0;
    if(sll != NULL )
        delete [] sll;
}

template <typename T>
void StaticLinkList<T>::DeleteElem(const int &n,T &e)
{
    if(Empty())
    {
        cout<<"链表为空,无法删除!"<<endl;
        return;
    }
    int x = head,y = head,z = avail;
    for(int i=0;i<n-1;i++)
        y = sll[y].next;
    x = sll[y].next;
    e = sll[x].data;
    sll[y].next = sll[x].next;
    avail = x;
    sll[avail].next = z;
    if(Empty())
    {
        avail = 0;
        head = -1;
        for(int i=0;i<size-1;i++)
           sll[i].next = i+1;
        sll[size-1].next = -1;
    }
}

template <typename T>
void StaticLinkList<T>::SetElem(const int &n,const T &e)
{
    if(Empty())
        return;
    int x = head;
    for(int i=0;i<n;i++)
        x = sll[x].next;
    sll[x].data = e;
}

template <typename T>
void StaticLinkList<T>::Reverse()
{
    if( Empty() || Getlength() == 1 )
        return;
    int a[Getlength()+1],x = head,j=0;
    while(x != -1)
    {
        a[j++] = sll[x].next;
        x = sll[x].next;
    }
    x = 0;
    int n = Getlength();
    for(int i = 1;i<= n;i++)
    {
        sll[x].next = a[n-i];
        x = sll[x].next;
    }
    sll[x].next = -1;

}

template <typename T>
int StaticLinkList<T>::Search(const T &e) const
{
    int pos = -1,x = head,i=0;
    while(x != -1)
    {
        if( e == sll[x].data )
            pos = i;
        x = sll[x].next;
        i++;
    }
    return pos;
}

template <typename T>
int StaticLinkList<T>::Getlength() const
{
    int num = 0,x = head;
    while(x != -1)
    {
        x = sll[x].next;
        if( x != -1)
            num++;
    }
    return num;
}


template <typename T>
bool StaticLinkList<T>::Full() const
{
    if(Getlength() == size - 1)
        return true;
    else
        return false;
}

template <typename T>
bool StaticLinkList<T>::Empty() const
{
    if(Getlength() == 0)
        return true;
    else
        return false;
}

template <typename T>
void StaticLinkList<T>::Output(ostream &out) const
{
    if( !Empty() )
    {
         out<<"实际静态链表:Head-->";
         out<<"sll["<<head<<']'<<"///"<<"-->";
         int x = head;
         x = sll[x].next;
         while( x!=-1 )
         {
             out<<"sll["<<x<<']'<<sll[x].data<<"-->";
             x = sll[x].next;
         }
         out<<"-1"<<endl;
    }
    else
        out<<"无实际静态链表"<<endl;
    if( !Full() )
    {
        out<<"可利用空间表:Avail-->";
        int x = avail,i = 1;
        for(int i=0;i<10 && x != -1;i++ )
         {
             out<<"sll["<<x<<']'<<"-->";
             x = sll[x].next;
         }
         out<<"-1";
    }
    else
        out<<"无可用空间"<<endl;
}

template <typename T>
ostream & operator<<(ostream &out,const StaticLinkList<T> &List)
{
    List.Output(out);
    return out;
}
#endif // STATICLINKLIST_H

你可能感兴趣的:(静态链表(C++实现)——基于数据结构(沈俊版)(初学者食用))