`
java-mans
  • 浏览: 11414858 次
文章分类
社区版块
存档分类
最新评论

一步一步写算法(之非递归排序)

 
阅读更多

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

在上面一篇博客当中,我们发现普通查找和排序查找的性能差别很大。作为一个100万的数据,如果使用普通的查找方法,那么每一个数据查找平均下来就要几十万次,那么二分法的查找呢,20多次就可以搞定。这中间的差别是非常明显的。既然排序有这么好的效果,那么这篇博客中,我们就对排序算做一个总结。

按照我个人的理解,排序可以分为两种:一种是非递归排序,它主要按照非递归的方法对数据进行排序,也就是说主要数据的移位和循环来完成;另外一种就是递归方法,我们在排列当前数据的时候首先把子数据排列有序,然后才会排列当前的数据。这种不断递归调用的方法就是递归排序。

非递归排序的方法很多,这里主要介绍冒泡排序、插入排序、希尔排序;递归的方法也不少,这里介绍的方法是快速排序、归并排序和堆排序。排序的内容很多,本篇博客主要介绍非递归排序,递归排序的内容主要在下一节内容解决。

(1)冒泡排序

冒泡排序的内容并不复杂。假设有n个数据需要排序,那么我们需要确定n个从大到小的数据,每一次都挑选第n大的数据是多少,并且放大相应的位置。直到所有的数据都排列整齐了,那么我们的排序就结束了。

void bubble_sort(int array[], int length)
{
	int inner = 0, outer = 0;
	int median = 0;

	if(NULL == array || 0 == length)
		return;

	for(outer = length-1; outer >= 1; outer --){
		for(inner = 0; inner < outer; inner ++){
			if(array[inner] > array[inner + 1]){
				median = array[inner];
				array[inner] = array[inner + 1];
				array[inner + 1] = median;
			}
		}
	}
}
那么这个程序有没有什么改进的地方呢?当然存在,如果发现在一次遍历循环之中,如果没有发生移位的现象,那么是不是可以判断这个排序可以结束了呢?朋友们可以好好思考一下这个问题?

void bubble_sort(int array[], int length)
{
	int inner = 0, outer = 0;
	int median = 0;
	int flag = 1;

	if(NULL == array || 0 == length)
		return;

	for(outer = length-1; outer >= 1 && flag; outer --){
		flag = 0;

		for(inner = 0; inner < outer; inner ++){
			if(array[inner] > array[inner + 1]){
				median = array[inner];
				array[inner] = array[inner + 1];
				array[inner + 1] = median;

				if(flag == 0)
					flag = 1;
			}
		}
	}
}

(2) 插入排序

插入排序的意思就是说,我们把数据分成两个部分,一部分是已经排好序的数据,一部分是当前还没有完成排序的数据。那么这么说来的话,排序的过程是不是就是把没有排序的数据逐个插入到已经排好序的队列中的过程呢。大家可以自己先试一下,然后再看看我的代码对不对?

void insert_sort(int array[], int length)
{
	int inner = 0;
	int outer = 0;
	int median = 0;
	if(NULL == array || 0 == length)
		return;

	for(outer = 1; outer <length; outer ++){
		for(inner = outer; inner >= 1; inner --){
			if(array[inner] < array[inner -1]){
				median = array[inner];
				array[inner] = array[inner -1];
				array[inner -1] = median;
			}else{
				break;
			}
		}
	}
}
那么插入排序有没有像冒泡排序那样的改进方法呢?其实没有。因为每一次插入排序的位置都是局部比较的结果,而冒泡排序每一次的内容都是全局最优的。这从数据比较的次数就可以看出来。


(3)希尔排序

希尔排序,我个人认为可以看成是冒泡排序的变种。它的基本思想是:首先按照一个序列递减的方法逐渐进行排序。比如说有10个数据,我们按照序列5、3、1的顺序进行排序。首先是5,那么我们对1和6、2和7、3和8、4和9、5和10进行排列;第二轮是3,那么对数据1、4、7、10排列,再对2、5、8进行排列,以及3、6、9排列;第三轮就和冒泡排序一样了,以此对每个数据进行排列。它的优势就是让整个队列基本有序,减少数据移动的次数,从而降低算法的计算复杂度。

void shell_sort(int array[], int length, int step)
{
	int inner = 0;
	int outer = 0;
	int median = 0;

	if(NULL == array || 0 == length)
		return;

	for(; step >= 1; step -=2){
		for(int index = 0; index < step; index ++){
			if((length -1) < (index + step))
				continue;
			else{
				outer = index + step;
				while( (outer + step) <= (length - 1))
					outer += step;
			}

			for(;  outer >= (index + step);  outer -= step){
				for(inner = index; inner <= outer - step; inner += step){
					if(array[inner] >= array[inner + step]){
						median = array[inner];
						array[inner] = array[inner + step];
						array[inner + step] = median;
					}
				}
			}
		}
	}
}

总结:

(1)上面的排序都是非递归程序,理解上不难,但是细节问题需要注意,特别是长度的问题

(2)代码编写的时候务必注意测试用例的设计

(3)如果可能的情况下,多使用已经验证的代码和函数


【预告: 下一篇博客介绍快速排序的内容】


分享到:
评论

相关推荐

    数据结构与算法.xmind

    有递归和非递归两种方式 双向链表 循环链表 树 二叉树 完全二叉树 堆 满二叉树 哈夫曼树 哈夫曼编码 二叉搜索树 AVL树 平衡二叉树 红黑树 多叉树 B树 查找...

    IOI国家集训队论文集1999-2019

    + [非完美算法](#非完美算法) + [提交答案题](#提交答案题) + [守恒思想](#守恒思想) + [极限法](#极限法) + [贪心](#贪心) + [压缩法](#压缩法) + [逆向思维](#逆向思维) + [穷举](#穷举) + [目标转换](#...

    数据结构(C++)有关练习题

    利用堆栈类,将本题a和b的代码改成非递归的方式。 实验报告要求: 按要求写出完整的实验代码; &lt;br&gt;实验四 综合(课程设计) 内容及步骤: 1、假定一维数组a[n]中的每个元素值均在[0,200]区间内,用C++...

    C语言通用范例开发金典.part1.rar

    1.4.11 中序非递归遍历二叉树(链式结构)(2) 177 范例1-65 中序非递归遍历二叉树 177 ∷相关函数:InOrderTraverse2函数 1.4.12 后序遍历二叉树(顺序结构) 180 范例1-66 后序遍历二叉树 180 ∷相关函数:...

    C语言通用范例开发金典.part2.rar

    1.4.11 中序非递归遍历二叉树(链式结构)(2) 177 范例1-65 中序非递归遍历二叉树 177 ∷相关函数:InOrderTraverse2函数 1.4.12 后序遍历二叉树(顺序结构) 180 范例1-66 后序遍历二叉树 180 ∷相关函数:...

    C 开发金典

    1.4.11 中序非递归遍历二叉树(链式结构)(2) 177 范例1-65 中序非递归遍历二叉树 177 ∷相关函数:InOrderTraverse2函数 1.4.12 后序遍历二叉树(顺序结构) 180 范例1-66 后序遍历二叉树 180 ∷相关函数:...

    计算机二级公共基础知识

    算法基本设计方法:列举法、归纳法、递推、递归、减半递推技术、回溯法。 (5)指令系统 所谓指令系统指的是一个计算机系统能执行的所有指令的集合。 (2)数据结构研究的3个方面 ① 数据集合中各数据元素之间所固有...

    JAVA上百实例源码以及开源项目

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

    JAVA上百实例源码以及开源项目源代码

     Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。  设定字符串为“张三,你好,我是李四”  产生张三的密钥对(keyPairZhang)  张三生成公钥(publicKeyZhang...

Global site tag (gtag.js) - Google Analytics