对象的多数组表示
用三个数组next key prev 分别表示链表的后继 数据 前驱。
以下的代码分别展示了基本的字典操作和如何申请分配内存。
//由于有些语言不支持指针,所以我们可以用多数组表示的静态双链表。
#include <iostream>
#include <time.h>
#include <windows.h>
using namespace std;
#define MAX 10//于表头的前驱和表尾的后继都不存放元素,所以实际能存放的有效元素个数比MAX少2个
#define Null -1
int head=Null,Free=0;
int j=0;
struct List
{
int next[MAX];
int key[MAX];
int prev[MAX];
};
int isIn(int *num,int index,int pat)//生成的随机数pat是否已经存在
{
int i=0;
for(i=0;i<index;++i)
if(pat==num[i])
return 1;
return 0;
}
int RAND(int *num)//随机抽取元素互异的key 这样key不会出现重复数值,易于以后的删除工作。
{
int result=0;
if (j>=MAX)
{
return Null;
}
while(1)
{
result=rand()%MAX;
if(!isIn(num,j,result))
{
num[j]=result;
j++;
break;
}
}
return result;
}
//链表初始化
void Initialization(struct List &T,int*num)
{
Free=RAND(num);//[1,MAX-1]之间的数随机选择一个作为表头元素下标
for (int i=0;i<MAX;i++)
{
T.key[i]=0;
T.prev[i]=0;
}
int p=Free;
for ( i=0;i<MAX-1;i++)
{
p=T.next[p]=RAND(num);
}
T.next[p]=Null;//链表最后的next指针为空。-1代表空
j=0;//结构体T初始化后,临时数组num下标设置为0.
}
//分配空间
int Allocate_object(struct List &T,int*num)
{
if (Free==Null)
{
cerr<<"out of space!"<<endl;
return Null;
}
else
{
int x=Free;
Free=T.next[x];
return x;
}
}
//释放空间
void Free_object(struct List &T,int x)
{
T.next[x]=Free;
Free=x;
}
//插入数据
void insert(struct List &T,int k,int *num)
{
int x=Allocate_object(T,num);//类似指针开辟一段内存空间
if (x==Null)
{
return;
}
T.next[x]=head;
T.key[x]=k;
if (head!=Null)
{
T.prev[head]=x;
}
head=x;
T.prev[x]=Null;
}
//查找数据
int search(struct List &T,int k)
{
int t=head;
if (head==Null)
{
cout<<"链表为空!无法查找!"<<endl;
return Null;
}
while (t!=-1&&T.key[t]!=k)
{
t=T.next[t];
}
if (t==Null)
{
cout<<"不存在这个数据!"<<endl;
return Null;
}
else
{
cout<<"待查找数据已经找到!"<<endl;
return t;//将待删除的数据下标返回,易于删除工作。
}
}
//删除数据
void Delete(struct List &T,int k)//删除特定值的删除函数
{
int p=0;
p=search(T,k);
if (p!=Null)
{
if (T.prev[p]!=Null)
{
T.next[T.prev[p]]=T.next[p];
}
else
{
head=T.next[p];
}
if (T.next[p]!=Null)
{
T.prev[T.next[p]]=T.prev[p];
}
cout<<"删除成功!"<<endl;
Free_object(T,p);
}
else
{
cout<<"待删除的数据不存在!无法删除!"<<endl;
}
}
void Print(struct List &T)
{
int i=head;
if (head==Null)
{
cout<<"此链表为空!"<<endl;
return;
}
while (i!=Null)
{
cout<<T.key[i]<<"->";
i=T.next[i];
}
cout<<endl;
}
void main()
{
struct List T;
srand((unsigned)time(NULL));
int num[MAX]={0};//临时存放next[MAX]和key[MAX]数组的值,目的是用于生成互异的随机数
cout<<"初始化链表中。";
for( int j=0; j <= 100; j++ ) // 打印百分比
{
cout.width(3);
cout << j << "%";
Sleep(40);
cout << "\b\b\b\b";//\b退格符号
}
cout << "\n";
Initialization(T,num);
Print(T);
cout<<"给链表添加数据中。";
for( j=0; j <= 100; j++ ) // 打印百分比
{
cout.width(3);
cout << j << "%";
Sleep(40);
cout << "\b\b\b\b";//\b退格符号
}
cout << "\n";
for (int i=0;i<MAX+1;i++)
{
int k=RAND(num);
insert(T,k,num);
}
insert(T,35,num);
Print(T);
cout<<"查找数据中。";
for( j=0; j <= 100; j++ ) // 打印百分比
{
cout.width(3);
cout << j << "%";
Sleep(40);
cout << "\b\b\b\b";//\b退格符号
}
cout << "\n";
search(T,6);
cout<<"删除数据中。";
for( j=0; j <= 100; j++ ) // 打印百分比
{
cout.width(3);
cout << j << "%";
Sleep(40);
cout << "\b\b\b\b";//\b退格符号
}
cout << "\n";
Delete(T,0);
Delete(T,2);
Delete(T,5);
Delete(T,500);
insert(T,25,num);
Print(T);
}
对象的单数组表示
用一个数组即可表示双链表,这种表示法比较灵活,因为它允许不同长度的对象存储于同一数组中。一般地我们考虑的数据结构多是由同构的元素构成,因此采用对象的多数组表示法足够满足我们的需求。
以下的代码分别展示了基本的字典操作和如何申请分配内存。
//我们用key next prev表示双链表,如果array[i-1]为key,那么array[i]为next,array[i+1]为prev。
#include <iostream>
#include <time.h>
#include <windows.h>
using namespace std;
#define MAX 120
#define Null -1
int head=0,Free=0;
int isIn(int *num,int index,int pat)//生成的随机数pat是否已经存在
{
int i=0;
for(i=0;i<index;++i)
if(pat==num[i])
return 1;
return 0;
}
int RAND(int *num,int &j)//随机抽取元素互异的key 这样key不会出现重复数值,易于以后的删除工作。
{
int result=0;
if (j==0)
{
num[j]=head;j++;
}
while(1)
{
if (MAX/3==0)//防止被除数为0
{
return Null;
}
else
{
result=(rand()%(MAX/3)) * 3 + 1;
}
if(!isIn(num,j,result))
{
num[j]=result;
j++;
break;
}
}
return result;
}
//分配空间
int Allocate_object(int *Array,int*num)
{
static x;
if (Free==Null)
{
cout<<endl;
cerr<<"out of space!"<<endl;
return Null;
}
else
{
x=Free;
Free=Array[x];
return x;
}
}
//释放空间
void Free_object(int *Array,int x)
{
Array[x]=Free;
Free=x;
}
//链表初始化
void Initialization(int *Array,int*num,int &j)
{
for (int i=0;i<MAX;i++)
{
Array[i]=0;
}
int p=RAND(num,j);
Free=head=p;
for (i=0;i<MAX/3-1;i++)
{
p=Array[p]=RAND(num,j);
}
Array[p]=Null;//链表最后的next指针为空。-1代表空
}
int insert(int *Array,int *num,int &j)
{
static p=head,q=Null;
int x=Allocate_object(Array,num);
if (p!=Null)
{
Array[p-1]=rand()%MAX+1;
Array[p+1]=q;
q=p;
p=Array[x];
}
else cout<<"链表开辟的内存空间不足! 无法插入!"<<endl;
return p;
}
//查找数据
int search(int *Array,int k)
{
int t=head;
if (Array[t-1]==0)
{
cout<<"链表为空!无法查找!"<<endl;
return Null;
}
while (t!=-1&&Array[t-1]!=k)
{
t=Array[t];
}
if (t==Null)
{
cout<<"不存在这个数据!"<<endl;
return Null;
}
else
{
cout<<"待查找数据已经找到!"<<endl;
return t;//将待删除的数据下标返回,易于删除工作。
}
}
//删除数据
void Delete(int Array[],int k)//删除特定值的删除函数
{
int p=0;
p=search(Array,k);
if (p!=Null)
{
if (Array[p+1]!=Null)
{
Array[Array[p+1]]=Array[p];
}
else
{
head=Array[p];
}
if (Array[p]!=Null)
{
Array[Array[p]+1]=Array[p+1];
}
Free_object(Array,p);
cout<<"删除成功!"<<endl;
}
else
{
cout<<"待删除的数据不存在!无法删除!"<<endl;
}
}
void Print(int *Array)
{
int i=head;int flag=1;
if (Array[head-1]==0)
{
cout<<"链表为空!"<<endl;
return;
}
while (flag)
{
if (Array[i]==Null)
{
flag=0;
}
cout<<Array[i-1]<<"\t";
i=Array[i];
}
}
void main()
{
int Array[MAX];
int num[MAX]={0};//临时存放数据的next指针的值,目的是用于生成互异的随机数
int j=0;
srand((unsigned)time(NULL));
cout<<"初始化链表中。";
for( int i=0; i <= 100; i++ ) // 打印百分比
{
cout.width(3);
cout << i << "%";
Sleep(40);
cout << "\b\b\b\b";//\b退格符号
}
cout << "\n";
Initialization(Array,num,j);
Print(Array);
cout<<"给链表添加数据中。";
for( i=0; i<= 100; i++ ) // 打印百分比
{
cout.width(3);
cout << i << "%";
Sleep(40);
cout << "\b\b\b\b";//\b退格符号
}
insert(Array,num,j);
insert(Array,num,j);
insert(Array,num,j);
insert(Array,num,j);
insert(Array,num,j);
for ( i=0;i<MAX/3;i++)
{
insert(Array,num,j);
}
Print(Array);
cout<<"查找数据中。";
for( i=0; i <= 100; i++ ) // 打印百分比
{
cout.width(3);
cout << i << "%";
Sleep(40);
cout << "\b\b\b\b";//\b退格符号
}
cout << "\n";
search(Array,5);
cout<<"删除数据中。";
for( i=0; i <= 100; i++ ) // 打印百分比
{
cout.width(3);
cout << i << "%";
Sleep(40);
cout << "\b\b\b\b";//\b退格符号
}
cout << "\n";
Delete(Array,5);
Delete(Array,6);
Delete(Array,7);
Delete(Array,7);
Delete(Array,6);
Print(Array);
}
//多数组的双链表实现已经更新,使其更符合书中代码,尤其是插入函数。