目的:通过实际操作静态单链表,掌握静态链表的储存结构以及熟悉静态链表的基本操作并进一步理解算法与程序的关系。
内容:用摘链的方法建立带头结点的静态单链表并对已创建的静态链表实现插入、删除、查找等基本操作。
静态链表简介:用数组来表示单链表,用数组元素的下标来模拟单链表的指针。静态链表由开两个域够成,data域存放数据元素,next域存放该元素的后继元素所在的下标。
单链表类的定义
#include<iostream>
#include<iomanip> //使用了setw()
using namespace std;
const int MaxSize=100;
struct Node
{
int data; //存放的数据
int next; //存放下标
}List[MaxSize];
class LinkList
{
public:
LinkList(); /*无参构造函数*/
LinkList(int a[],int n); /*建立有n个元素的链表*/
~LinkList(){}
void Insert(int i,int x); /*在第i个位置中插入元素值为X的结点*/
int Length(); /*求链表的长度*/
int Get(int i); /*按位查找,在链表中查找第i个结点的元素值*/
int Locate(int x); /*按值查找*/
int Delete(int i); /*删除链表中第i个结点*/
void PrintList(); /*按序号依次输出各元素*/
private:
int first; //静态链表的头指针
int avail; //空闲链的头指针
};
成员函数的定义
LinkList::LinkList()
{
first=0;
avail=0;
List[0].next=-1; //创建空的链表
for(int i;i<MaxSize-1;i++)
{
List[i].next=i+1;
}
List[MaxSize-1].next=-1; //置空闲链结束标志
}
LinkList::LinkList(int a[],int n)
{
int s;
if(n>=MaxSize||n<=0)
{
throw "输入有误";
}
first=0; //初始化静态链表的头指针
List[0].next=avail=1; //初始化空闲链的头指针
for(int i=0;i<MaxSize-1;i++)
{
List[i].next=i+1;
}
List[MaxSize-1].next=-1;
for(int i=0;i<n;i++)
{
s=avail;
List[s].data=a[i]; //将数据放入空闲链最前端
avail=List[avail].next; //将此时空闲链最前端赋给空闲链的头指针
}
List[s].next=-1;
}
//插入算法
void LinkList::Insert(int i,int x)
{
int s;
s=avail;
avail=List[avail].next;
List[s].data=x;
for(int p=0;p<MaxSize-1;p++)
{
if(p==i)
{
List[s].next=List[p].next;
List[p].next=s;
}
}
}
//求静态链表的长度
int LinkList::Length()
{
int count=0;
int p;
p=first;
while(List[p].next!=-1)
{
p=List[p].next;
count++;
}
return count;
}
//遍历双链表的数据
void LinkList::PrintList()
{
int p;
p=List[first].next;
while(p!=-1)
{
cout<<List[p].data<<endl;
p=List[p].next;
}
}
//按位查找数据
int LinkList::Get(int i)
{
if(i>=0&&i<=MaxSize)
{
return List[i].data;
}
else
{
throw "位置";
return 0;
}
}
//按值查找数据
int LinkList::Locate(int x)
{
int count;
count=List[first].next;
for(count;count!=-1;count++)
{
if(List[count].data==x)
{
return count;
}
}
return 0;
}
//删除静态链表中第i个结点
int LinkList::Delete(int i)
{
if(i>0&&i<MaxSize)
{
int q;
i=i-1;
q=List[i].next; //暂存被删除节点的下标
List[i].next=List[q].next; //摘链
List[q].next=avail; //将节点q插在空闲连的最前端
avail=q; //空闲链头指针avail指向节点q
return List[q].data;
}
else
{
throw "位置";
return 0;
}
}
主函数代码:
int main()
{
int n,i;
int a[100];
cout<<"******************"<<endl;
cout<<"*请输入数组的大小"<<endl;
cout<<"******************"<<endl;
cin>>n;
cout<<'\n'<<endl;
cout<<"******************"<<endl;
cout<<"*请输入数组元素*"<<endl;
cout<<"******************"<<endl;
for(i=0;i<n;i++)
{
cin>>a[i];
}
LinkList one(a,n);
cout<<'\n'<<endl;
cout<<"~~~~~~~~~~~~~~~~~~"<<endl;
cout<<"线性表的长"<<one.Length()<<endl;
cout<<'\n'<<"线性表中的内容:"<<endl;
one.PrintList(); //输出线性表的数据
//按位查找
int s;
cout<<"~~~~~~~~~~~~~~~~~~"<<endl;
cout<<'\n'<<endl;
cout<<"**********************"<<endl;
cout<<"*请输入要查找数据的序号:"<<endl;
cout<<"**********************"<<endl;
cin>>s;
cout<<'\n'<<'\n'<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
cout<<'\n'<<"您所查询的数据为";
cout<<one.Get(s)<<endl;
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
//按值查找
int x;
cout<<'\n'<<"**********************"<<'\n'<<"*请输入要查找的数据:";
cout<<'\n'<<"**********************"<<endl;
cin>>x;
cout<<'\n'<<'\n'<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
cout<<'\n'<<"你所查找的值所在的位置为:"<<one.Locate(x)<<endl;
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
//按序号删除数据
int k;
cout<<'\n'<<"**************************"<<'\n'<<"*请输入需要删除的数据序号:";
cout<<'\n'<<"**************************"<<endl;
cin>>k;
cout<<'\n'<<'\n'<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
cout<<'\n'<<"删除成功!你所删除的数据为:"<<one.Delete(k)<<endl;
cout<<'\n'<<"线性表的内容为:"<<endl;
one.PrintList(); //输出线性表的数据
cout<<'\n'<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
return 0;
}
输入和查询数据:
删除数据
心得:
1.一开始不理解静态链表的储存机制,不懂如何编写静态链表的构造函数,然后通过查找相关的资料进行参考,才明白静态链表的储存结构。
2.理解静态链表最主要的有两部分,第一部分就是插入:从空闲链(以avail为头指针的链)的最前端摘下一个结点,将该结点插入静态链表中(以first为头指针的链);第二部分就是删除:将被删除的结点从静态链表中摘下,再插入空闲链的最前端。
3.在定义成员函数的时候,就可以体会到静态链表的‘好处’就是在插入和删除操作的时候,只需要修改游标,不需要移动表中的元素。