假设以带头结点的单链表表示有序表,单链表的类型定义如下:
typedef struct node{
DataType data;
struct node *next;
}LinkNode, *LinkList;
编写算法,从有序表A中删除所有和有序表B中元素相同的结点。
void DelEqual(LinkList La,LinkList Lb){ //伪代码
// La 和 Lb 分别存放 A 和 B 有序链表的头指针
LinkList pa,pb,r; // r指向要删除的结点
pa = La; // pa指向A的头结点
pb = Lb->next; // pb指向B的头结点的下一个结点
while(pa->next&&pb){ // 循环条件:pa->next和pb所指的结点都存在
if(pa->next->data < pb->data)
pa = pa->next;
else{
//下面为什么用while,而不用if,后面的例子可以解释
while(pa->next->data == pb->data){
r = pa->next;
pa->next = r->next;
free(r);
}
pb = pb->next;
}
}
}
代码解释:
1、由于La指向A的头结点,执行pa = La;
语句,让pa指向跟La相同的结点,即 pa也指向A的头结点。执行pb = Lb->next;
语句,让pb指向B的头结点的下一个结点。
2、pa的next指向元素为3的结点并且pb指向元素为3的结点,满足while(pa->next&&pb)
的循环条件。由于pa->next->data
为3, pb->data
也为3,不满足if(pa->next->data < pb->data)
的条件,所以执行else中的while(pa->next->data == pb->data)语句,由于满足循环条件,执行r = pa->next; pa->next = r->next; free(r);
让 r 指向pa的next结点,将 r 的next赋值给pa的next,即pa的next指向第二个元素为3的结点,第一个元素为3的结点所用的内存通过free(r)释放掉。
3、A中第一个元素为3的结点被删除后,此时pa依旧指向A的头结点,pb依旧指向B中元素为3的结点。依旧满足while(pa->next->data == pb->data)
的循环条件,接着执行r = pa->next; pa->next = r->next; free(r);
让 r 指向pa的next结点,将 r 的next赋值给pa的next,即pa的next指向元素为5的结点,第二个元素为3的结点所用的内存通过free(r)释放掉。
4、由于不满足while(pa->next->data == pb->data)
的循环条件,接下来执行pb = pb->next;
语句
5、接下来执行while(pa->next&&pb)
,满足循环条件。不满足if(pa->next->data < pb->data)
的条件,满足while(pa->next->data == pb->data)
的条件,接着执行r = pa->next; pa->next = r->next; free(r);
即A中元素为5的结点被删除。
6、接下来由于不满足while(pa->next->data == pb->data)
的循环条件,执行pb = pb->next;
语句,pb依次往后移动。
7、当pb指向元素为8的结点时。由于满足if(pa->next->data < pb->data)
,执行
pa = pa->next;
8、pa指向元素为7的结点,此时pa的next为空,不满足while(pa->next&&pb)
的循环条件,算法结束。