1.实验要求:
找到循环链表的最小值并删除该最小值后输出
2.错误算法思路:
void Delete_min(LinkList L)
{
LinkList p, s;//建立两个LinkList 类型的变量p,s
int i=0;
int count = 0;
int location = 0;
LinkList current = L->next;//工作指针,用来指向被删结点的前一个
s = (LinkList)malloc(sizeof(LNode));
s->data = L->next->data;//新结点存入L链表的首元结点的数据
p = L->next;//指针p指向L的首元结点
while (p != L)//由于L是一个循环链表,所以结束循环的条件就是,p不是指回前面附加结点
{
count++;
if (p->data < s->data)
{
s->data = p->data;
s = p;
location = count;
}
p = p->next;
}
location = location - 2;;
while (current != L && i < location)//将指针current指向被删结点的前一个
{
current = current->next;
i++;
}
LinkList t= current->next;
current->next = t->next;//拉上拉链
delete t;
L->data--;
}
3.出错原因:
①主要是在找到最小结点的while循环里中s->data = p->data;s = p;这两个语句,仔细想想,如果一开始找到的最小结点是在中间,s就会指向这个结点然后如果在后面有又出现了一个结点数据是比一开始那个小的,那么此时原来那个结点的data域就会被改变,变得和p的data域一样了
②s结点是新建出来用来存储最小值的,但是到后面这个结点就删不去了,因为,空间已经被新建出来了,仔细想想,如果只是单独用来存储最小值的数据的话,其实不用新建结点来储存的
③其实找到被删结点的前一个结点的算法不用那么复杂,因为原来的s已经是指向被删结点了,所以直接再设一个工作指针current,让他遍历链表,while(current->next!=s)的时候current=current->next,这样就很容易就找到了
4.补充知识点
①void Delete(LinkList L)与void Delete(LinkList &L),函数参数的区别:
加了&的就是引用,没加的就是没引用;如果不引用,就是无法改变指针L的指向的,但可以改变它指向的数据,因为它是新建了个指针,指向用一个位置,所以如果不引用,去改变函数内指针的指向的话,是无法改变实参里面传入指针的指向,此时改的就是新建指针的指向,因此对于不改头指针指向的功能函数来说,形参引用和不引用就没区别
②如果只是单独用来存储最小值的数据的话,其实不用新建结点来储存的,直接设一个整型变量存就好了!!!!新建结点还删不去
③在删除链表结点的算法中,新建的指针,一定要指向被删结点,就是要先摘下结点
④找到被删结点的前一个结点的算法不用那么复杂,因为原来的s已经是指向被删结点了,所以直接再设一个工作指针current,让他遍历链表,while(current->next!=s)的时候current=current->next,这样就很容易就找到了
⑤当新建链表的结点,分配空间使用malloc函数的时候,删除这个结点要用free()或者delete ,如果是用new新建的话,删除就要用delete。删除指针时,用delete就可以了,malloc在stdlib.h头文件里,要提前包括进来
5.易错点:
①利用删除算法时,注意要先把被删结点摘下,就是要先设置一个工作指针,指向被删结点,然后最后再delete掉这个工作指针
②最后别忘记了将链表长度减一
③存数据不一定要用结点存,用一个整型变量即可
6.心得
①写代码之前一定要先把算法写出来!!!!
②学会前面的四条知识点
③删除链表的时候,链表长度最后一定要减一!!!
7.优化算法如下:
第一步:找到并存储链表的最小值数据。可以先设置两个个工作指针变量,其中一个工作指针p用来遍历循环链表,另一个工作指针s用指向循环最小值的结点,便于后面进行删除
然后设置一个整型变量用来存储链表里面的最小值,整型变量的初始值为首元节点的数值。
当遍历过程中结点的data域小于整型变量时,将其赋值给整型变量
第二步:找到被删结点的前一个结点。另设一个工作指针current,用一个while循环,当current->next不等于s指针时(这个s指针指向的是链表的最小值结点),current一直往
往后移动,直到找到最小值结点的前一个结点
第三步:套用删除算法,将最小值结点删除
第四步:将链表的长度减一。就是将附加头结点的data域减一(事先此区域存的是链表长度)
8.优化算法源码实现如下:
void Delete_min(LinkList &L)
{
LinkList p, s=L->next;//建立两个LinkList 类型的变量p,s
int i=0;
LinkList current = L->next;//工作指针,用来指向被删结点的前一个
int Save_min = L->next->data;
p = L->next;//指针p指向L的首元结点
while (p != L)//由于L是一个循环链表,所以结束循环的条件就是,p不是指回前面附加结点
{
if (p->data < Save_min)
{
Save_min = p->data;
s = p;//s指向了最小的结点
}
p = p->next;
}
while (current ->next!=s)//将指针current指向被删结点的前一个
{
current = current->next;
}
current->next = s->next;//s已经指向被删结点了,所以直接拉上拉链拉上拉链
free(s);//现在要删去s指针指向的结点,而不是删除指针,而这个结点分配空间当初使用malloc()函数的,因此用free()
L->data--;
}
详细代码和运行过程参见数据结构第四周作业循环链表文件