void zhijiecharusort(LinkList& l)//直接插入排序
{// 使用指针p先保存下L中未排序元素(无序区中)的信息
使用指针p先保存下L中未排序元素(无序区中)的信息
LinkList p = l->next->next;//第一个节点有序
l->next->next = NULL;
// 由于为了构造有序区,已经将待排序元素的第一个元素放在有序区中了,
// 所以从第二个元素开始遍历,也就是p = L->next->next。
while (p)//p指向无序区
{
// 每循环一次p后移一位,直至p == NULL.
// 进行插入有序区的操作时会改变p->next的值所以需要选保存一下
LinkList q = p->next;
// 为方便比较,用一个指针pre,指向有序区。(重点)
LinkList pre = l;//为什么不能等于l->next
// 遍历有序区中的所有元素,直至有序区末尾或者找到:
// p所指的元素 大于 pre的next所指的元素为止,
while (pre->next != NULL && pre->next->data < p->data)//pre->next->data < p->data一旦不符合这个条件就成:pre->data < p->data&&pre->next->data > p->data
pre = pre->next; //pre->next == NULL跳出循环,即pre是有序区最后一个节点
// 找到比p大的节点后,执行插入操作,因为插入操作需要用到
// 被插入节点的前驱节点,所以在比较时,用了pre->next来和p比较
p->next = pre->next;
pre->next = p;
// 用q把p的值恢复过来,使得循环继续指向无序区的下一个节点
p = q;//往后移动1位因为:LinkList q = p->next;
}
}
直接插入排序就是:
先从待排序的元素中取出第一个元素。
取出的这个第一个元素当作有序区的第一个元素。
接着从待排序的元素中取出第二个元素。
然后将第二个元素插入到有序区中的合适位置,也就是,将第二个元素与第一个元素比较,谁小谁就排在有序区的前面。
接着,在待排序的元素中取第三个元素,然后再在有序区中比较,直至取遍所有待排序的元素。
例题
有一个带头节点的单链表 L (至少有一个数据节点),设计一个算法使其元素递增有序排列。
在算法讲授的过程中,以问题为研究对象,按照提出问题,分析问题,解决问题,总结问题的求解过程。例如:在将冒泡排序算法时,(1)用一个形象的图示介绍冒泡排序的基本思想;(2)提出问题,要完成冒泡排序需要解决哪些关键问题,这 是问题分解思想,问题分解体现开放性思维(3)引导学生通过排序过程的分析应该如何解决这些关键问题,这实际贯彻了一种抽象分级的思想(4)最后把这些问题连在一起,完成冒泡排序算法的设计。
分析
使用直接插入排序算法进行排序。
- 首先,我们需要构造出一个有序区,也就是构造一个存放有序区的列表。
-
// 使用原链表L构造了一个有序区,有序区中只有一个元素, // 这个元素是链表L的开始节点(头节点之后的那个节点) L->next->next = NULL; - 但是,发现将原链表L构造成有序区后发现,原链表的信息丢失了(开始节点之后的节点都没有了,变成了NULL),所以,在构造有序区之前需要保存下开始节点之后的信息。
// 使用指针p先保存下L中未排序元素(无序区中)的信息
p = L->next->next;
// 使用原链表L构造了一个有序区,有序区中只有一个元素,
// 这个元素是链表L的开始节点(头节点之后的那个节点)
L->next->next = NULL;
- 接下来的任务就是遍历无序区中的元素,将它们一个一个的取出来。
-
// 使用指针p先保存下L中未排序元素(无序区中)的信息 p = L->next->next; // 使用原链表L构造了一个有序区,有序区中只有一个元素, // 这个元素是链表L的开始节点(头节点之后的那个节点) L->next->next = NULL; // 由于为了构造有序区,已经将待排序元素的第一个元素放在有序区中了, // 所以从第二个元素开始遍历,也就是p = L->next->next。 while(p != NULL){ p = p->next; // 每循环一次p后移一位,直至p == NULL. } - 每次从无序区中取一个元素后,接着应该将其和有序区中元素进行比较。
-
// 使用指针p先保存下L中未排序元素(无序区中)的信息 p = L->next->next; // 使用原链表L构造了一个有序区,有序区中只有一个元素, // 这个元素是链表L的开始节点(头节点之后的那个节点) L->next->next = NULL; // 由于为了构造有序区,已经将待排序元素的第一个元素放在有序区中了, // 所以从第二个元素开始遍历,也就是p = L->next->next。 while(p != NULL){ // 为方便比较,用一个指针pre,指向有序区。 pre = L; // 遍历有序区中的所有元素,直至有序区末尾或者找到: // p所指的元素 大于 pre的next所指的元素为止, while(pre->next != NULL && pre->next->data < p->data) pre = pre->next; p = p->next; // 每循环一次p后移一位,直至p == NULL. } - 经过比较过后,可以知道无序区中的第一个元素在有序区中的位置,接下来将其插入有序区中。
-
// 使用指针p先保存下L中未排序元素(无序区中)的信息 p = L->next->next; // 使用原链表L构造了一个有序区,有序区中只有一个元素, // 这个元素是链表L的开始节点(头节点之后的那个节点) L->next->next = NULL; // 由于为了构造有序区,已经将待排序元素的第一个元素放在有序区中了, // 所以从第二个元素开始遍历,也就是p = L->next->next。 while(p != NULL){ // 每循环一次p后移一位,直至p == NULL. // 进行插入有序区的操作时会改变p->next的值所以需要选保存一下 q = p->next; // 为方便比较,用一个指针pre,指向有序区。 pre = L; // 遍历有序区中的所有元素,直至有序区末尾或者找到: // p所指的元素 大于 pre的next所指的元素为止, while(pre->next != NULL && pre->next->data < p->data) pre = pre->next; // 找到比p大的节点后,执行插入操作,因为插入操作需要用到 // 被插入节点的前驱节点,所以在比较时,用了pre->next来和p比较 p->next = pre->next; pre->next = p; // 用q把p的值恢复过来,使得循环继续指向无序区的下一个节点 p = q; } -
在算法讲授的过程中,以问题为研究对象,按照提出问题,分析问题,解决问题,总结问题的求解过程。例如:在将冒泡排序算法时,(1)用一个形象的图示介绍冒泡排序的基本思想;(2)提出问题,要完成冒泡排序需要解决哪些关键问题,这 是问题分解思想,问题分解体现开放性思维(3)引导学生通过排序过程的分析应该如何解决这些关键问题,这实际贯彻了一种抽象分级的思想(4)最后把这些问题连在一起,完成冒泡排序算法的设计。。。。。。。更重要:算法设计完成后,要及时进行梳理,重新厘清思路,就像过河一样,别人给河里放了几块垫脚石,我们过了河之后,要回过头来看看垫脚石是否舒服,学习人家怎么做的,以后遇到类似情况我们是否也能做这样的工作,这样才能培养学生的算法设计能力。
-
完整的代码
-
void sort(LinkList * &L){ LinkList *p,*pre,*q; p = L->next->next; // 先保存下L的第二个元素,因为下一步要将L变成只有一个元素的有序表。 L->next->next = NULL; // 将L变成只有一个元素的有序表 // 从L的第二个元素开始遍历整个L直至表尾 while(p != NULL){ q = p->next; pre = L; // 先用pre来保存L。 while(pre->next !=NULL && pre->next->data < p->data) // 遍历pre所指向的有序表L,直至找到比p大的节点 pre = pre->next; p->next = pre->next; pre->next = p; p = q; } }王红梅:数据结构从概念到c++----教师用书:0.2.4算法的抽象分级(page6)
-
在算法讲授的过程中,以问题为研究对象,按照提出问题,分析问题,解决问题,总结问题的求解过程。例如:在将冒泡排序算法时,(1)用一个形象的图示介绍冒泡排序的基本思想;(2)提出问题,要完成冒泡排序需要解决哪些关键问题,这 是问题分解思想,问题分解体现开放性思维(3)引导学生通过排序过程的分析应该如何解决这些关键问题,这实际贯彻了一种抽象分级的思想(4)最后把这些问题连在一起,完成冒泡排序算法的设计。。。。。。。更重要:算法设计完成后,要及时进行梳理,重新厘清思路,就像过河一样,别人给河里放了几块垫脚石,我们过了河之后,要回过头来看看垫脚石是否舒服,学习人家怎么做的,以后遇到类似情况我们是否也能做这样的工作,这样才能培养学生的算法设计能力。
-
在形式化思维方法 方面,通过描述算法的过程向学生展示设计算法的思路和方法,建立抽象化的思想并掌握相关技术,培养抽象分级的意识和能力。按照上述问题求解的过程,找到每个关键问题的解决方法后,不要急着用描述算法的语言(如c++)描述算法,而是采用::图示理解问题及求解思想------伪代码描述-----c++描述---的3级模式描述算法。一方面培养抽象分级的能力;一方面锻炼伪代码描述算法的能力,这两种能力往往学生是欠缺的。
-
采用抽象分级讲授算法,通过讲过程讲思路讲方法,培养学生的逻辑思维能力和开放式思维能力。在解决问题的过程中学会将问题拆开,将一个大问题拆成几个这问题来思考,将一个子问题拆成几个抽象的逻辑步骤来解决。
-
首先学会分析问题,从问题给定的条件(输入)出发,找到思考问题的入口点,从入口出发寻找解决问题的途径,不断提出子问题,解决子问题直到解决本原问题;或分析问题,从问题的结论(输出)出发,思考为得到这个结论应该解决哪些具体问题,不断提出子问题,解决子问题直到解决本原问题。
1万+

被折叠的 条评论
为什么被折叠?



