• 沒有找到結果。

所得到的结点地址(下标)存入 t 中;不难看出,当 AV 表非空时,摘下了第一个结点 给用户。当用户不再需要某个结点时,需通过该结点的相对地址 t 将它还给 AV,交给 AV 表 的结点链在了 AV 的头部,而不能调用系统的 free()函数。相关语句为:

sd[t].next=AV;

AV=t;

2.4.6 案例分析

案例 4

问题:链表基本算法的实现。

算法分析:编写链表基本操作函数,实现下面的操作:

(1)初始化一链表。

(2)在主函数中建立一选项菜单,使用户可选择进行插入、查找、删除或退出等操作。

data next

SL=0 0 4

1 a4 5

2 a2 3

3 a3 1

4 a1 2

5 a5 -1

AV=6 6 7

7 8

8 9

9 10

10 11

11 -1

表 SL

表 AV

(3)调用插入函数建立一个链表。

(4)查找用户从键盘输入的指定值的元素,如果该元素存在,返回该元素值在链表中的 第一个位置;否则返回指定值不存在的提示。

(5)查找用户从键盘输入的指定位置的元素,如果该位置合适,返回该位置的元素值;

否则返回指定位置不合理的提示。

(6)删除用户从键盘输入的指定值的元素,如果该元素值存在,返回删除成功的提示,

否则返回用户所输入元素值不存在的提示。

(7)删除用户从键盘输入的指定位置的元素,如果指定位置合适,返回删除成功的提示,

否则返回用户所输入的位置不合适的提示。

(8)遍历并输出顺序表中的元素。

(9)在进行插入、查找、删除等操作后,必须及时输出链表中的元素,便于观察操作结果。

算法实现:

#include<stdio.h>

#include<alloc.h>

typedef struct LNode{

int data;

struct LNode *next;

}LNode,*LinkList;

void InitLinkList(LinkList *p) {

*p=NULL;

}

void InsertLinkList(LinkList *p,int elem,int j) {

int i;

LinkList u,q,r;

u=malloc(sizeof(LNode));

u->data=elem;

for(i=0,r=*p;i<j && r!=NULL;i++) {

q=r;

r=r->next;

} if(r==*p) *p=u;

else

q->next=u;

u->next=r;

}

int DeleteLinkList(LinkList *p,int elem) { LinkList q,r;

q=*p;

if(q->data==elem)

{*p=q->next;

free(q);

return 0;

}

for(;q->data!=elem && q!=NULL; r=q, q=q->next);

if(q==NULL) return 1;

if(q->data==elem) {r->next=q->next;

free(q);

return 0;

}

else return 1;

}

int FindLinkList(LinkList p,int elem) {

int i;

for( i=1;(p->data!=elem) && p!=NULL; p=p->next, i++);

return(p==NULL)? -1:i;

}

void OutputLinkList(LinkList p) { LinkList q=p;

printf("链表为:\n");

while(q!=NULL) {

printf("%4d",q->data);

q=q->next;

}

printf("\n");

}

void main() {

LinkList p;

int op,i,j,r;

InitLinkList(&p);

while(1) {

printf("选择操作 1:在指定位置插入元素 2:查找指定的元素\n");

printf("3:删除指定的元素 0:Exit\n");

fflush(stdin);

scanf("%d",&op);

switch(op) {

case 0:

return;

case 1:

printf("输入要插入的元素值及位置:");

算法分析:依次取原链表中的每个结点,将其作为第一个结点插入新链表,指针 p 用来 指向当前结点,p 为空时结束。

算法实现:

void reverse (Linklist H) { LNode *p;

p=H->next; //p 指向第一个数据结点 H->next=NULL; //将原链表置为空表 H while (p)

{ q=p; p=p->next;

q->next=H->next; //将当前结点插到头结点的后面 H->next=q;

} }

算法 2.15

该算法只是对链表顺序扫描一遍即完成了倒置,时间性能为 O(n)。

案例 6

问题:已知单链表 L,写一算法,删除其重复结点,即实现如图 2.24 所示的操作。图 2.24

(a)所示为删除前,(b)所示为删除后。

图 2.24 删除重复结点 算法分析:

用指针 p 指向第一个数据结点,从它的后继结点开始到表的结束,找与其值相同的结点 并删除之;p 指向下一个;依此类推,p 指向最后结点时算法结束。

算法实现:

void pur_LinkList(LinkList H) { LNode *p,*q,*r;

p=H->next; //p 指向第一个结点 if(p==NULL) return;

while (p->next) { q=p;

while (q->next) //从*p 的后继开始找重复结点 { if (q->next->data==p->data)

{ r=q->next; //找到重复结点,用 r 指向,删除*r q->next=r->next;

free(r);

} //if else q=q->next;

10 ∧

15 15 18

H 10

(a)

18 ∧

10 15 H

(b)

} //while(q->next)

p=p->next; //p 指向下一个结点,继续 } //while(p->next)

}

算法 2.16

该算法的时间性能为 O(n2)。

*案例 7

问题:在带头结点的静态链表 SL 的第 i 个结点之前插入一个值为 x 的新结点。

算法分析:

可设静态链表的存储区域 sd 为全局变量,指针是结点为数组的下标。

算法实现:

int Insert_SList( int SL, datatype x, int i) { int p,s;

p=SL; j=0;

while(sd[p].next!=-1 && j<i-1)

{p=sd[p].next;j++;} //找第 i-1 个结点 if(j==i-1)

{ if(AV!=-1) //若 AV 表还有结点可用 {t=AV;

AV=sd[AV].next; //申请、填装新结点 sd[t].data=x;

sd[t].next=sd[p].next; //插入 sd[p].next=t;

return 1; //正常插入成功返回 }

else{printf("存储池无结点");return 0;}

//未申请到结点,插入失败 else{printf("插入的位置错误");return -1;}

//插入位置不正确,插入失败 }

算法 2.17

读者可将该算法和算法 2.12 进行比较,除了一些描述方法有些区别外,算法思路是相同的。

相關文件