由于顺序结构存在的增删困难,还有其他操作也较为不方便的原因为了让结构更加灵活,多变,更充分利用存储空间,有了链表。
在链式结构中,不同于顺序结构的通过存储位置上的关系来表示逻辑上的关系,链式结构中通过“箭头”——指针,的引导来表示相互关系。
因此在链表中,将每个数据分为两部分:本生的数据部分(数据域),和相互关系的部分——指针域。
C语言的结构体如下:
typedef struct LNode{
ElemType data;
struct LNode *next;
}
该结构的大概存储结构通过一个查找数据来分析:
Status GetElem_L(LinkList L,int i;ElemType &e)
{
p=L->next;
j=1;
while(p&&j<i)
{
p=p->next;
j++;
}
e=p->data;
}
该例子中,通过指针的“引导”实现了数据间的联系。
区别与顺序表中的增和删,由于链表关系有指针域来联系,因此在改变关系时候,只需要改变指针的“指引”就ok。
如增添数据:
主要的步骤就是该表增添位置的前一个结点的“指向”,以及添加结点的指向。类似于只需改变铁链中的2的“缺口”,而其他的结点并不需要改变。
s->next=p->next;
p->next=s;
最终实现就是在添加一个遍历让指针指向需要增添的位置上and创建新结点。
Status ListInsert(LinkList& L,int i;ElemType e){
for(p=L,j=0;p&&j<i-1;j++)
{
p=p->next;
}
s=(ElemType*)malloc(ElemType);
s->data=e;
s->next=p->next;
p->next=s;
return ok;
}
删除一样,只不过要通过free()来释放删除掉的结点:
Status Linkdelete(LinkList &L,int i;ElemType &e){
for(p=L,j=0;p&&j<i;j++)
{
p=->next;
}
q=p->next;
p->next=p->next->next;
e=q->data;
free(q);
return ok;
}
综合运用是:2个链表的合并
算法思想与前一节一致,就是在最后剩余的部分链表上更加简便了。
void mergeList(Linklist& L1,LinkList& L2,LinkList& L3){
pa=L1->next;
pb=L2->next;
pc=L3=L1;
while(p1&&p2)
{
if(p1->data<=p2->data)
{
p3->next=p1;
p3=p1;
p1=p1->next;
}
else{
p3->next=p2;
p3=p2;
p2=p2->next;
}
if(pa)
p3->next=p1;
if(pb) p3->next=p2;
}
以上是动态链表的建立,但是链表的本质就是多了一个指针域来代表逻辑关系,而不是用存储位置上的关系来表示,但是我们可以看出通过同样的数组类型同样可以添加一个“指针”来表示相互之间的关系,这就是——静态链表
就是创建一个新类:
typedef struct{
ElemType data;//数据
int cur;//等同于指针
}
其中的 cur 代表数组中的“点”的下一个“点”的位置。
在增删数据的时候只需要同链表相同,改变“结点”的“指针”即可。
在数据的查询中虽然看似像链表,但实际上的查看顺序是按照数组的存储顺序依依查看的:
int LocateElem(SlinkList S,ElemType e){
i=S[0].cur;//i表示查找到的位置
while(i&&S[i].data!=e){
i=S[i].cur;
}
return i;
}
与链表的区别是,在增删中的开辟和释放没有了系统提供的函数,需要自己建立。
建立方法是建立一个“垃圾库”,删除的数就把它放进这个垃圾库中,需要的数就把它提出来。本质就是建立一个备用链表。
具体步骤为3步:1、将空间的数据初始化为一个静态链表。2、建立一个备用空间中得到一个节点。3、将节点连接到备用链表中。
第一步--初始化静态链表:
void InitSpace(SLinklist &space){
for(i=0;i<MaxSize-1;i++)
space[i].cur=i+1;/*因为数组的下标是从0到n-1,而在静态链表中cur指向下一个节点*/
space[MaxSize-1].cur=0;//最后的指针域为NULL
}
第二步--从备用空间中得到一个结点。
第三步--链接
直接以(A-B)并(B-A)为例。
void difference(SLinkList & space,int i){
InitSpace(space);
S=mallocS(space);//生成头结点
r=S;
scanf(m,n)//A and B的元素个数
for(int j=1;j<m;j++)//建立A的链表
{
i=mallocS(space);
scanf(sapce[i].data);
space[r].cur=i;//插入到表尾
r=i;
}
space[r].cur=0;
for(........).......//插入B
/*指向A中元素分别查找,如果没有则放置到一个备份链表中。*/
if(k==space[r].cur)
{
i=mallocS(space);
space[i].data=b;
space[i].cur=space[r].cur;
space[r].cur=i;
}
else /*说明元素已存在,删除掉*/
}