简单说明
在实现链表类的数据结构时,可采用的方式一般有动态链表和静态链表的方式。
动态链表
动态链表的定义:
typedef struct LinkNode
{
ElemType data;//data area
LinkNode *link;//point area
}LNode,*LinkList ;
通过定义可以看出,动态链表的物理存储结构不是连续的,由单独的结点串联起来组成,使用时,可定义带头结点与不带头结点的动态链表,一般在使用时会引入一个指向链表结点的指针,通过这个指针对链表进行操作。
下面是对链表的一部分操作:
LinkList Create_Link()
{//创建带有头结点的动态链表
LinkList p=(LinkList)malloc(sizeof(LNode));
p->next=NULL;
return p;
}
void Insert(LinkList &L,int i,int e)
{//将元素e插入到链表的位置i中
LinkList NewNode=(LinkList)malloc(sizeof(LNode));
NewNode->data=e;
LinkList p=L;
int cnt=1;
if(i<0) return ERROR;//判断i是否合法
while(p && cnt<i)
{
p=p->next;
cnt++;
}
if(p||cnt<i) return ERROR;
NewNode->next=p->next;
p->next=NewNode;
}
int Length(LinkList &L)
{//返回量表长度
int i;
LinkList p=L;
while(p)
{
p=p->next;
i++;
}
return i;
}
int Locate(LinkList &L,int e)
{
int i=1;
LinkList p=L;
while(p)
{
if(p->data==e) return i;
p=p->next;
i++;
}
if(!p)
return ERROR;
}
循环链表
在定义时只需使链表的尾结点的指针域指向链表的头结点,即可构成循环量表,可以在链表的任意位置循环,只是循环条件需要改变。
双向链表
对结点加入指向它的前驱的指针,可便于在某结点前插入新的结点。
定义方法:
typedef struct LinkNode
{
ElemType data;//data area
LinkNode *prior;
LinkNode *next;//point area
}LNode,*LinkList;
静态链表
静态链表实际上是利用结构体数组来实现链表的思想,结构体数组由数据域以及用于存储相对位置的成员组成。
定义:
typedef struct SLinkList
{
ElemType data;//存储数据
int cur;//游标用于存储当前结点的后继结点的下标
}SLinkList[MAXSIZE],componend;
静态链表较特殊的一点是还存在一条将空闲位置连接起来的链表,一般将其称之为备用链表,备用链表的作用是回收数组中未使用或之前使用过(目前未使用)的存储空间,留待后期使用。备用链表的头结点一般为下标为零的结点,且备用链表的头结点通常不存储数据元素,数据链表的头结点一般使用下表为1的结点,可以置空,方便对其后继元素进行删除、插入新元素等操作。
#include<cstdio>
#include<iostream>
#define MAXSIZE 10
using namespace std;
typedef int ElemType;
typedef struct SLinkList
{
ElemType data;
int cur;
}componend,SLinkList[MAXSIZE];
//创建备用表
void Create_List(SLinkList &L)
{
int i;
for(i=0;i<MAXSIZE;i++)
{
L[i].cur=i+1;
}
L[i-1].cur=0;//将备用链表的最后一个结点指向头结点
}
nt Malloc_List(SLinkList &L)
{//取出备用链表的空余结点
int i;
i=L[0].cur;
if(L[0].cur)
{
L[0].cur=L[i].cur;//备用链表的头节点游标指向下一个结点
}
return i;//返回的i作为可用节点的下标
}
void Display_List(SLinkList &L)
{
int i=2,j=1;
while(L[i].cur)
{
printf("elem[%d]=%d\n",j,L[i].data);
j++;
i=L[i].cur;//无法打印数据链表最后一个元素
}
printf("elem[%d]=%d",j,L[i].data);//打印数据链表最后一个元素
}
int Search_Elem(SLinkList &L,ElemType x)
{//搜索某元素在数据链表中的位置
int i=2;
while(L[i].cur)
{
if(x==L[i].data)
{
return i;
}
i=L[i].cur;
}
if(x==L[i].data)
{
return i;
}
return 0;
}
最好使用静态链表的表头代替上述操作中从i=2开始向后进行操作的代码,表头可以随删除插入等操作做出改变,可以令算法更为灵活。