算法补习-第三天-排序(下)
2016-03-03 08:39
260 查看
插入排序:直接插入排序,希尔排序,归并排序
直接插入排序:
将一个新的数据插入到一个有序数组中,并继续保持有序。例如有一个长度为N的无序数组,进行N-1次的插入即能完成排序;第一次,数组第1个数认为是有序的数组,将数组第二个元素插入仅有1个有序的数组中;第二次,数组前两个元素组成有序的数组,将数组第三个元素插入由两个元素构成的有序数组中......第N-1次,数组前N-1个元素组成有序的数组,将数组的第N个元素插入由N-1个元素构成的有序数组中,则完成了整个插入排序。
方法:将数据插入有序数组时,如a[5]={3,5,6,7}中插入4,需将a[1]=4,后边的元素后移,为节省内存,从最后一位开始后移,即先将a[3]的4移到a[4]上,再依次往前后移,即为a[4]=a[3],扩大为a[j]=a[j-1],从最后一位到第二位需要一次后移,移完后再将数据插入第二位a[1].
代码:
将数组按dk间距分成dk个小的数组
例数组a[5]={5,6,4,3,8},其索引值对应为0,1,2,3,4,按间距dk分为dk=5/2个数组,即a[0],a[2],a[4]与a[1],a[3],分别将其进行直接插入排序。再将dk--,进入同上循环,此时间距dk为1,即将a[0],a[1],a[2],a[3],a[4]进行直接插入排序。再进行dk--,dk>=1为假,跳出循环。
注意:基准元素为i=dk前的元素,即a
4000
[0],a[1],其在循环过程中分别被当前值temp比较,
归并排序:
思路:
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
首先考虑下如何将将二个有序数列合并。这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。
解决了上面的合并有序数列问题,再来看归并排序,其的基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了?
可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。
函数功能:
merge():将一个左右两部分 分别 已排好序的 数组二分成两个子数组,将子数组每一项挨个比较,得到排序后的数组,用于归并。
mergeSort():用于分治,将数组不停二分,直至二分后的结果为两个子数。
代码:
#include<iostream>
using namespace std;
void merge(int a[],int L,int M,int R)
{
int LEFT_SIZE = M - L;
int RIGHT_SIZE = R - M + 1;
int left[LEFT_SIZE];
int right[RIGHT_SIZE];
int i,j,k;
for(i=L;i<M;i++)
{
left[i-L] = a[i];
}
for(i=M;i<=R;i++)
{
right[i-M] = a[i];
}
i=0;j=0;k=L;
while(i<LEFT_SIZE && j<RIGHT_SIZE)
{
if(left[i]<right[j])
{
a[k] = left[i];
i++;
k++;
}
else
{
a[k] = right[j];
j++;
k++;
}
}
while(i<LEFT_SIZE)
{
a[k] = left[i];
i++;
k++;
}
while(j<RIGHT_SIZE)
{
a[k] = right[j];
j++;
k++;
}
}
void mergeSort(int a[],int L,int R)
{
if(L == R)
{
return;
}
else{
int M = (L + R) / 2;
mergeSort(a,L,M);
mergeSort(a,M+1,R);
merge(a,L,M+1,R);
}
}
int main()
{
int a[6] = {5,6,4,3,8,9};
int i;
mergeSort(a,0,5);
for(i=0;i<6;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}
直接插入排序:
将一个新的数据插入到一个有序数组中,并继续保持有序。例如有一个长度为N的无序数组,进行N-1次的插入即能完成排序;第一次,数组第1个数认为是有序的数组,将数组第二个元素插入仅有1个有序的数组中;第二次,数组前两个元素组成有序的数组,将数组第三个元素插入由两个元素构成的有序数组中......第N-1次,数组前N-1个元素组成有序的数组,将数组的第N个元素插入由N-1个元素构成的有序数组中,则完成了整个插入排序。
方法:将数据插入有序数组时,如a[5]={3,5,6,7}中插入4,需将a[1]=4,后边的元素后移,为节省内存,从最后一位开始后移,即先将a[3]的4移到a[4]上,再依次往前后移,即为a[4]=a[3],扩大为a[j]=a[j-1],从最后一位到第二位需要一次后移,移完后再将数据插入第二位a[1].
代码:
#include<iostream> using namespace std; void insert_sort(int*array,unsigned int n) { int i,j; int temp; for(i=1;i<n;i++) { temp=*(array+i); for(j=i;j>0&&*(array+j-1)>temp;j--) { *(array+j)=*(array+j-1); } *(array+j)=temp; } } int main() { int a[5] = {5,6,4,3,8}; insert_sort(a,5); for(int i=0;i<5;i++) { cout<<a[i]<<" "; } cout<<endl; return 0; }希尔排序:
将数组按dk间距分成dk个小的数组
例数组a[5]={5,6,4,3,8},其索引值对应为0,1,2,3,4,按间距dk分为dk=5/2个数组,即a[0],a[2],a[4]与a[1],a[3],分别将其进行直接插入排序。再将dk--,进入同上循环,此时间距dk为1,即将a[0],a[1],a[2],a[3],a[4]进行直接插入排序。再进行dk--,dk>=1为假,跳出循环。
注意:基准元素为i=dk前的元素,即a
4000
[0],a[1],其在循环过程中分别被当前值temp比较,
#include<iostream> using namespace std; void ShellSort(int a[],int n) { int dk = (n-1)/2; int i,j,temp; while(dk>=1) { //一趟shell排序,对dk个序列分别进行直接插入排序 for(i=dk;i<=n;i++)//需要插入的元素为dk及其以后的数 { temp = a[i];//将需插入元素放入缓冲区 for(j=i-dk;j>=0&&a[j]>temp;j=j-dk)//建立以dk为间距的小数组,进行比较 { a[j+dk] = a[j]; } a[j+dk] = temp; } dk--; } } int main() { int a[5] = {5,6,4,3,8}; ShellSort(a,5); for(int i=0;i<5;i++) { cout<<a[i]<<" "; } cout<<endl; return 0; }
归并排序:
思路:
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
首先考虑下如何将将二个有序数列合并。这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。
解决了上面的合并有序数列问题,再来看归并排序,其的基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了?
可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。
函数功能:
merge():将一个左右两部分 分别 已排好序的 数组二分成两个子数组,将子数组每一项挨个比较,得到排序后的数组,用于归并。
mergeSort():用于分治,将数组不停二分,直至二分后的结果为两个子数。
代码:
#include<iostream>
using namespace std;
void merge(int a[],int L,int M,int R)
{
int LEFT_SIZE = M - L;
int RIGHT_SIZE = R - M + 1;
int left[LEFT_SIZE];
int right[RIGHT_SIZE];
int i,j,k;
for(i=L;i<M;i++)
{
left[i-L] = a[i];
}
for(i=M;i<=R;i++)
{
right[i-M] = a[i];
}
i=0;j=0;k=L;
while(i<LEFT_SIZE && j<RIGHT_SIZE)
{
if(left[i]<right[j])
{
a[k] = left[i];
i++;
k++;
}
else
{
a[k] = right[j];
j++;
k++;
}
}
while(i<LEFT_SIZE)
{
a[k] = left[i];
i++;
k++;
}
while(j<RIGHT_SIZE)
{
a[k] = right[j];
j++;
k++;
}
}
void mergeSort(int a[],int L,int R)
{
if(L == R)
{
return;
}
else{
int M = (L + R) / 2;
mergeSort(a,L,M);
mergeSort(a,M+1,R);
merge(a,L,M+1,R);
}
}
int main()
{
int a[6] = {5,6,4,3,8,9};
int i;
mergeSort(a,0,5);
for(i=0;i<6;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}
相关文章推荐
- WPF InkCanvas MouseDown及MouseLeftButtonDown事件不触发的代替事件
- 关于用mybatis调用存储过程时的入参和出参的传递方法
- NSFileManager的应用
- TaintDroid下载与编译(二):JDK的下载与安装
- 连续整数固定和
- 值得推荐的C/C++框架和库(深度好文)
- UVa——1593Alignment of Code(string重定向+vector数组)
- 浅谈JAVA设计模式
- linux如何挂载U盘
- Java版本-----商店购物系统
- swift 数据持久化之归档
- 格式工厂 转换格式 mp4 保留视频清晰度 经验之谈
- question_011-JAVA之Collection
- RedHat linux下jdk的安装
- 安卓排除美颜相机等第三方相机直接调用系统相机处理方法
- Data scientist's tool笔记
- 原子操作和线程的并发执行
- USC CSCI 585 Specialization Hierarchy
- 图解:如何在LINUX中安装VM-Tools
- SQL读书笔记(五)