码迷,mamicode.com
首页 > 编程语言 > 详细

【自考】数据结构之排序

时间:2015-08-30 23:07:23      阅读:303      评论:0      收藏:0      [点我收藏+]

标签:插入排序

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">
</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">
</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><img src="http://img.blog.csdn.net/20150830221537061?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
</span>
<span style="font-family:FangSong_GB2312;font-size:24px;color:#ff0000;"><strong style="background-color: rgb(255, 255, 255);">定义</strong></span>

排序就是将一组对象,按照规定的次序,进行重新排列的过程。它主要为检索服务!


分类

排序可分为两大类:内部和外部

内部:待排序的记录全部存放在计算机内存中,然后进行排序的过程。

外部:待排序的记录数量很大,内存不能存储全部记录,需要对外存进行访问的排序过程。

在内部排序中可分为四类:插入、交换、选择和归并。下面一一为大家介绍一下:

插入

插入排序又可分为多种方法,本篇博客中只介绍直接插入排序(Straight Insertion Sorting)

它的基本思想是,依次将每个记录插入到一个已排好序的有序表中去,从而得到一个新的、记录数增加1的有序表。  

<pre name="code" class="html"><pre name="code" class="javascript">
<pre name="code" class="vb">1.	void InsertSort(List R,int n){  
2.	<span style="color:#33cc00;">//对顺序表R进行直接插入排序</span>
3.	    int i,j ;  
4.	    for(i=2; i<=n; i++){  <span style="color:#33cc00;">//n为表长,从第二个记录起进行插入</span>
5.	        if(R[0]<R[i]){    <span style="color:#33cc00;">//第i个记录复制为岗哨</span>
6.	            j = i-1 ;  
7.	            while(R[0].key<R[j].key){  <span style="color:#33cc00;">//与岗哨比较,直至<=岗哨键值</span>
8.	                R[j+1] = R[j] ;         <span style="color:#33cc00;">//将第i个记录,赋值给第i+1个记录</span>
9.	                j-- ;  
10.	            }  
11.	            R[j+1] = R[0] ;           <span style="color:#33cc00;">//将第i个记录插入到序列中</span>
12.	        }  
13.	    }  
14.	}  

在直接插入排序算法的描述中,我们会设置“岗哨”。那么,这里的“岗哨”是什么意思?

上面的代码中,List型变量的第0个记录可以闲置或用来暂存某个记录值,可以用作“岗哨”。所以,使用R[0]有两个作用。

1、  进入查找循环之前,保存R[i]的值,使得不至于因记录的后移而丢失R[i]中的内容

2、  起到岗哨作用,在while循环中“监视”数组下标变量j是否越界,一旦越界(j<1),R[0]自动控制while循环的结束,从而避免了while循环中每一次都要检测j是否越界。这一技巧的使用,使得测试循环条件的时间减少一半左右。

 

交换

基本思想:比较两个记录键值的大小,如果这两个键值的大小出现逆序,则交换这两个记录。这样一来,键值较小的记录向序列前部移动,大的向后移动。。

在交换排序中,主要有两种方法:冒泡排序法和快速排序法。

冒泡步骤:

1、  将第一和第二个记录的键值比较,若为逆序,则将两个记录交换

2、  继续比较第二和第三个记录的键值

3、  一次类推,直到完成第n-1和第n个记录的键值比较交换为止

技术分享

从上图中可以看出,键值较小的记录好比起泡一样向上漂浮,键值较大的则向下沉,所以,称为冒泡排序。


1.	<span style="color:#33cc00;">//冒泡排序 </span> 
2.	void BubbleSort(List R,int n){  
3.	    int i,j,temp,endsort;  
4.	    for(int i=1; i<=n; i++){   <span style="color:#33cc00;">//排序次数</span>
5.	         endsort=0;  <span style="color:#33cc00;">//在每次排序之前,先将它设置为0,若在气泡中交换了记录,置为1</span>
6.	        for(int j=1; j<=n-i-1; j++){   <span style="color:#33cc00;">//记录位置</span>
7.	            if(R[j].key > R[j+1].key){  
8.	                temp = R[j] ;  
9.	                R[j] = R[j+1];  
10.	                R[j+1] = temp ;  
11.	                 endsort=1;
12.	            }  
13.	        }  
14.	         If (endsort==0) break;   <span style="color:#33cc00;">//当一次循环结束时,在检查endsort,若为0,终止算法</span>
15.	    }  
16.	}  

快速排序

基本思想:

1、  在N个记录中取第一个记录键值为基准(通常)

2、  通过第一趟排序,将待排序记录分为两个独立部分:<=键值、>键值。

3、  以二叉树先序遍历的形式,对两部分记录分别排序,最后达到整个序列有序的效果。


通过上面的图,我们可以看出:

1、  它是以第一个记录的键值45为基准

2、  从第n个记录向前,找到第一个小于45的键值,然后互换位置

3、  从第2个记录向后,找到第一个大于45的键值,然后互换位置

4、  按照前两部的顺序进行循环

 

选择

基本思想:每一次在n-i+1(i=1,2,~~~,n-1)个记录中选取键值最小的记录作为有序序列的第i个记录。

在选择排序中,主要有两种方法:直接选择排序和堆排序。

直接选择

基本思想:在第i次操作中,通过n-i次键值的比较,从n-i+1个记录中选出键值最小的记录。


1.	<span style="color:#33cc00;">//直接选择 </span>
2.	void SelectSort(List R,int n){  
3.	    int min,i,j;  
4.	    for(int i=1; i<=n-1; i++){   <span style="color:#33cc00;">//每次循环,选出最小键值</span>
5.	        min=i;  <span style="color:#33cc00;">//假设第i个键值为最小</span>
6.	        for(j=i+1; j<=n; j++)  
7.	            if(R[j].key < R[min].key) min=j; <span style="color:#33cc00;">//记录键值较小记录的下标 </span>
8.	            if(min !=i) swap(R[min],R[i]);  <span style="color:#33cc00;">//将最小键值记录和交换第i个记录交换</span>
9.	        }  
10.	    }  

堆排序

基本思想:在输出堆顶的最小键值之后,使得剩余的n-1个键值重新建成一个堆,则可得到n个键值中的次最小值。如此反复执行,便能得到有序序列,称之为堆序列。

最小堆:若有一个关键字{K1,K2,~~~,Kn}满足Ki<=K2i,Ki<=K2i+1,并且,i=1,2,~~~,n/2,则称这个n个键值的序列为最小堆。

 

堆排序实现要解决两个问题:

1、  如何将初始序列建成堆

2、  如何在输出堆顶元素之后调整剩余元素成为一个新堆

 

第一个问题解决方法

1、  将要排序的键值看成一棵完全二叉树的结点

2、  根据完全二叉树性质最后一个非终结点是第n/2个元素,所以,筛选只需从第n/2个元素开始至以前的元素结束。

由上图所示,n为8,n/2为4,所以从34开始执行,到65结束。

 

第二个问题解决方法

1、  设最后一个叶结点为新的根

2、  新根与左右子树的根节点进行比较,选出最小值,确定新根节点元素的方向(左子树 or 右子树)

3、  将最小值放在堆顶,其他值进行调整

4、  重复循环

 

归并排序(Merge Sorting)

基本思想

与前三种排序的不同之处是,要求待排序列是由若干个有序子序列组成。归并排序的核心操作是将两个或以上的有序表合并成一个新的有序表。

二路归并

1、  将每相邻的两个记录合并,使每个子序列包含两个记录。

2、  再将上述子序列两两合并

3、  如此反复,直至得到一个长度为n的有序序列为止,排序结束

技术分享


 






版权声明:本文为博主原创文章,未经博主允许不得转载。

【自考】数据结构之排序

标签:插入排序

原文地址:http://blog.csdn.net/xiada_you_comeon/article/details/48110529

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!