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