数据结构------快排及另类快排思想解决问题
2015-09-27 16:28
387 查看
快速排序原理:选出一个基数,把小于这个基数的,放在它的前面,大于这个基数的放在基数后面。
首先:我觉得大家肯定都很疑惑,算法这个东西,思想掌握了,但是代码的实现,又有很多种,就比如拿今天我们的主人公,快速排序来说吧,这个算法有两种形式,一种是不加哨兵的算法,一种是加上哨兵的算法,我曾经一度以为这两个形式是两种算法,让我走了好多弯路。我想我这样说肯定是的不到大家的理解的,那么我们接下来就进入今天的主要内容。
第一种,不带哨兵的算法,这个时候我们首先看一下,怎么去理解这个东西。首先我们回忆一下,排序算法的思想,就是选取一个基数,把小于基数的数,放在基数的前面,把大于这个数的放在基数的后面。其实大家也许已经看出来了,其实重点就在怎么放,怎么比较。
首先把代码贴出来
首先我们来分析一下这段代码。核心部分是while里面的那部分,首先当low小于high的时候,我们的代码是一直进行第一次循环的,因为要遍历完所有的数。
1.这个时候,我们刚开始进行比较的时候,我们一定要让high先动,为什么呢,因为这个时候我们让默认的基数为low指向的地方。然后如果low小于high则一直让high一直向前移动,这个时候如果high小于了low,则对high与low进行交换。
2.交换完了,等于说high的位置变成了,基数的位置。然后我们对此时的low与high进行比较,如果low小于high则一直,low++,如果low大于了high则停下来,交换。
3.这个时候,while里面的第二个while也执行完了,这个时候,毫无疑问,需要进行需要判断,是否结束while循环,如果low没有与high重合,则步骤如上。
4.当while循环结束的时候,也就是,这个时候(假设是第一次循环的结束),我们把数组分为两部分,left到low,high到right,这个时候我们进行左半部分的排序,然后进行递归,左半部分,会继续分为更小的两部分,直到递归到两个数,也就是重合的时候,这个时候,就会return。我们的递归调用函数,会一直跳转回,第一次分割的地方,然后进行右半部分的递归调用。
也许大家看完我的文字描述,还有一些疑惑,下来我来上一幅图
快速排序函数的递归调用
2.第二种,带哨兵的快速排序。
首先我们在这里说这两个的区别:
不带哨兵的函数:我们在交换数组里面的值时候,我们总是,当基数为low的时候,把low与high直接一换,则此时high为基数,然后在用low与high进行比较,满足交换的条件了,用low与high交换,这个时候基数又变成high,当俩重合的时候,基数刚好就在他们中间。
带哨兵的函数:开始进行比较的时候,对基数进行记录为tmp,然后用low与high进行比较,当low与high进行重合的时候,把low与high位置的数放在left的位置,然后把tmp放在low的位置。
下面我们来看一道,有关快排思想的运用的题:给你一个数组,按序列排好如:1,4,7,9,11,12,14,15,这个时候,输入一个数字,例如15,输出数组里两个数,刚好等于15,如1+14 = 15;
首先:我觉得大家肯定都很疑惑,算法这个东西,思想掌握了,但是代码的实现,又有很多种,就比如拿今天我们的主人公,快速排序来说吧,这个算法有两种形式,一种是不加哨兵的算法,一种是加上哨兵的算法,我曾经一度以为这两个形式是两种算法,让我走了好多弯路。我想我这样说肯定是的不到大家的理解的,那么我们接下来就进入今天的主要内容。
第一种,不带哨兵的算法,这个时候我们首先看一下,怎么去理解这个东西。首先我们回忆一下,排序算法的思想,就是选取一个基数,把小于基数的数,放在基数的前面,把大于这个数的放在基数的后面。其实大家也许已经看出来了,其实重点就在怎么放,怎么比较。
首先把代码贴出来
#include <iostream> using namespace std; void Swap(int &a, int &b) { int tmp; tmp = a; a = b; b = tmp; } void QuickSort(int *arr,int left,int right) { if (arr == NULL) return; int low = left; int high = right; //不设置哨兵的写法 while (low < high) { while (low < high && arr[low] <= arr[high]) high--; Swap(arr[low], arr[high]); while (low < high && arr[low] <= arr[high]) low++; Swap(arr[low], arr[high]); } //在这里把要排序的数字,分成两部分,然后选取前半部分,进行递归算法 if (low - 1 >= left) QuickSort(arr, left, low-1); //当第一部分的前半部分进行递归完了之后,在计算他左边的 if (high + 1 <= right) QuickSort(arr, high+1, right); }
首先我们来分析一下这段代码。核心部分是while里面的那部分,首先当low小于high的时候,我们的代码是一直进行第一次循环的,因为要遍历完所有的数。
1.这个时候,我们刚开始进行比较的时候,我们一定要让high先动,为什么呢,因为这个时候我们让默认的基数为low指向的地方。然后如果low小于high则一直让high一直向前移动,这个时候如果high小于了low,则对high与low进行交换。
2.交换完了,等于说high的位置变成了,基数的位置。然后我们对此时的low与high进行比较,如果low小于high则一直,low++,如果low大于了high则停下来,交换。
3.这个时候,while里面的第二个while也执行完了,这个时候,毫无疑问,需要进行需要判断,是否结束while循环,如果low没有与high重合,则步骤如上。
4.当while循环结束的时候,也就是,这个时候(假设是第一次循环的结束),我们把数组分为两部分,left到low,high到right,这个时候我们进行左半部分的排序,然后进行递归,左半部分,会继续分为更小的两部分,直到递归到两个数,也就是重合的时候,这个时候,就会return。我们的递归调用函数,会一直跳转回,第一次分割的地方,然后进行右半部分的递归调用。
也许大家看完我的文字描述,还有一些疑惑,下来我来上一幅图
快速排序函数的递归调用
2.第二种,带哨兵的快速排序。
首先我们在这里说这两个的区别:
不带哨兵的函数:我们在交换数组里面的值时候,我们总是,当基数为low的时候,把low与high直接一换,则此时high为基数,然后在用low与high进行比较,满足交换的条件了,用low与high交换,这个时候基数又变成high,当俩重合的时候,基数刚好就在他们中间。
带哨兵的函数:开始进行比较的时候,对基数进行记录为tmp,然后用low与high进行比较,当low与high进行重合的时候,把low与high位置的数放在left的位置,然后把tmp放在low的位置。
#include <iostream> using namespace std; void Swap(int &a, int &b) { int tmp = 0; tmp = a; a = b; b = tmp; } void QuickSort(int *arr, int left, int right) { if (arr == NULL) return; int low = left; int high = right; int tmp = arr[left]; while (low < high) { while (low < high && arr[high] >= tmp) high--; while (low < high && arr[low] <= tmp)low++; if (high != low) { Swap(arr[high], arr[low]); } } //数据归位 arr[left] = arr[low]; arr[low] = tmp; if (low - 1 >= left) QuickSort(arr, left, low - 1); if (high + 1 <= right) QuickSort(arr, high + 1, right); }这个代码贴出来,大家可以在电脑上自己运行一把,思想什么的都一样,我就不赘述了。
下面我们来看一道,有关快排思想的运用的题:给你一个数组,按序列排好如:1,4,7,9,11,12,14,15,这个时候,输入一个数字,例如15,输出数组里两个数,刚好等于15,如1+14 = 15;
#include <iostream> using namespace std; void func(int *a,int szie_num,int aim_num) { int *p = a; int *q = p + szie_num; while (p != q) { if ((*p + *q) > aim_num) { q--; } else if ((*q + *p) < aim_num) { p++; } else break; } printf("%d + %d = %d", *p, *q, aim_num); }
相关文章推荐
- [数据结构]二叉排序树
- 数据结构-线性表-栈-递归
- 数据结构 4____计算时间复杂度
- 数据结构,多项式运算,C++,链表
- 一元多项式的加减乘除运算,C++语言描述,数据结构实验
- [数据结构]Hash表初学(数组链表)
- 数据结构顺序栈的创建、初始化、出栈、入栈及销毁
- 数据结构基础 之 最长递增子序列
- (数据结构笔记)二叉查找树的实现
- 数据结构学习笔记——树
- 数据结构学习总结——预备知识
- 数据结构学习总结——数据结构概述
- 2,Add Two Number (LinkList Math)
- 1,Two sum (Hashtable Array)
- Java数据结构与算法之有序数组的插入和合并
- iOS —— JSON 数据结构及其解析方式
- 中国大学MOOC-陈越、何钦铭-数据结构-2015秋 03-树3 Tree Traversals Again (25分)
- iOS ——XML数据结构及其两种解析数据的方式SAX 、DOM
- 【软考之路】-数据结构
- 数据结构中的概念问题