排序算法的分类:
排序:基本排序:{交换排序:冒泡排序,快速排序。(快速排序相当于冒泡排序的升级)
{选择排序:选择排序,堆排序(堆排序相当于选择排序的升级)
{插入排序:直接插入排序,Shell排序(希尔排序相当于直接插入排序的升级)
{归并排序
多路归并排序:
一:交换排序
1:交换排序的主体操作是对数组中的数据不断进行交换操作。
2:交换排序种类:交换排序主要有冒泡排序和快速排序。
1:冒泡排序
(1)冒泡排序流程
——(1)对数组中的各元素,一次比较相邻的两个元素的大小
——(2)如果前面的数据大于后面的数据,就交换着两个数据。经过第一轮的多次比较排序之后,便可将最小的数据排好
——(3)在用同样的方法把剩下的数据逐个进行比较,最后便可按照从小到大的顺序排好数组个数据的顺序。
(2)冒泡代码分析
优点:思路简单直观。
缺点:执行的步骤有点长,效率不是很高。
时间效率:没有数据交换时间复杂度O(n),最坏的情况为数组逆序,时间复杂度为O(n^2)
空间效率:仅使用了一个辅存单元。
(3)冒泡排序代码
public void bubblesort(){
int[] data={10,9,8,7,6,5,4};
System.out.println("排序之前");
System.out.println(java.util.Arrays.toString(data));
int n=data.length;
for(int i=0;i<n-1;i++){
for(int j=0;j<n-1-i;j++){
if(data[j]-data[j+1]>0){
int temp=data[j];
data[j]=data[j+1];
data[j+1]=temp;
}
}
}
System.out.println("排序之后:\n");
System.out.println(java.util.Arrays.toString(data));
}
2:快速排序
(1)快速排序流程
——(1)首先设定一个分界值,通过该分界值将数据分成左右两个部分。
——(2)将大于等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。
此时,左边部分中的各元素都小于等于分界值,而右边部分中各元素都大于等于分界值。
——(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,
同样将左边放置较小值,右边放置较大值。右边的数据也做这样的处理。
——(4)重复上述过程。
(2)快速排序代码分析
快速排序,平均O(nlogn),最坏O(n^2),空间O(logn),不稳定
时间效率:待排序序列本身已经有序或逆向有序时,快速排序的时间复杂度为Ο(n 2 ),
而在有序时插入排序的时间复杂度为Ο(n)。
空间效率:
(3)快速排序代码
public class AMoNiStack {
public static void main(String[] args){
AMoNiStack a=new AMoNiStack();
int[] b={1,4,5,32,7,54,2};
a.quicksort(b,0,b.length-1);
for(int i:b){
System.out.print(" "+i);
}
}
public void quicksort(int a[],int start,int end){
int i=start;
int j=end;
boolean flag=true;
if(i>=j){
return ;
}
while(i!=j){
if(a[i]>a[j]){
int temp=a[i];
a[i]=a[j];
a[j]=temp;
flag=!flag;
}
if(flag){
j--;
}else{
i++;
}
}
i--;
j++;
quicksort(a,start,i);
quicksort(a,j,end);
}
}
二:选择排序
1:简单选择排序
(1)选择排序流程
——(1)首先从原始数组中选择最小的1个数据,将其和第一个位置的数据交换。
——(2)接着从剩下的n-1个数据中选择次小的一个元素,将其和第二个位置的数据对换。
——(3)然后这样不断重复,直到最后两个数据完成对换。至此,便完成了对原始数组的从小到大的排序。
(2)选择排序分析:
选择排序在对n个数据执行的过程中,无论原数据是否有顺序,都需要进行n-1步的中间排序。
优点:思路简单
缺点:执行代码优点长,效率不是很高。
效率:时间复杂度O(n^2),空间效率,只需一个辅存空间
简单选择排序,平均O(n^2),最坏O(n^2),空间O(1),不稳定
(3)选择排序代码
public class shuzuA {
static final int SIZE=10;
public static void main(String[] args){
int[] shuzu=new int[SIZE];
int i;
for(i=0;i<SIZE;i++){
shuzu[i]=(int)(100+Math.random()*(100+1));
}
System.out.println("排序前数组:");
for(i=0;i<SIZE;i++){
System.out.print(shuzu[i]+" ");
}
System.out.println();
selectSort(shuzu);
System.out.println("排序后数组:");
for(i=0;i<SIZE;i++){
System.out.print(shuzu[i]+" ");
}
}
public static void selectSort(int[] a){
int index,temp;
for(int i=0;i<a.length-1;i++){
index=i;
for(int j=i+1;j<a.length;j++){//为了找到index这个索引之后的最小值的索引。
if(a[j]<a[index]){
index=j;//每次比较完,index是最小值的索引。
}
}
if(index!=i){//交换两个数
temp=a[i];
a[i]=a[index];
a[index]=temp;
}
}
}
}
2:堆排序(Heap Sort基于选择排序思想的)
(1)堆排序流程
{什么是堆结构:堆结构是一种树结构,是一个完全二叉树。}
(2)堆排序分析
堆排序,平均O(nlogn),最坏O(nlogn),空间O(1),不稳定
(3)堆排序代码
public class DemoJoin{
static final int SIZE=10;
static void heapSort(int a[],int n){
int i,j,h,k;
int t;
for(i=n/2-1;i>=0;i--){
while(2*i+1<n)
{
j=2*i+1;
if((j+1)<n){
if(a[j]<a[j+1])
j++;
}
if(a[i]<a[j])
{
t=a[i];
a[i]=a[j];
a[j]=t;
i=j;
}
else
break;
}
}
System.out.print("原数据构成的堆:");
for(h=0;h<n;h++)
System.out.print(" "+a[h]);
System.out.println();
for(i=n-1;i>0;i--){
t=a[0];
a[0]=a[i];
a[i]=t;
k=0;
while(2*k+1<i){
j=2*k+1;
if((j+1)<i)
{
if(a[j]<a[j+1])
j++;
}
if(a[k]<a[j])
{
t=a[k];
a[k]=a[j];
a[j]=t;
k=j;
}
else
break;
}
}
}
public static void main(String[] args) {
int[] shuzu=new int[SIZE];
int i;
for(i=0;i<SIZE;i++){
shuzu[i]=(int)(100+Math.random()*(100+1));
}
System.out.println("排序前的数组:");
for(i=0;i<SIZE;i++){
System.out.print(shuzu[i]+" ");
}
System.out.println();
heapSort(shuzu,SIZE);
System.out.println("排序后的数组:");
for(i=0;i<SIZE;i++){
System.out.print(shuzu[i]+" ");
}
System.out.println();
}
}
三:插入排序
1:直接插入排序(Insertion Sort)
(1)直接插入排序流程
——(1)首先对数组的前两个数据进行从小到大的排序。
——(2)接着将第3个数据与排好序的两个数据比较,将第3个数据插入到何时的位置,
——(3)然后,将第四个数据插入到已排好序的前3个数据中。
——(4)不断重复上述过程,直到把最后一个数据插入到合适的位置。最后,便完成了对原始数据从小到大的排序。
(打扑克,边抓牌,边捋牌)
(2)直接插入排序分析
插入排序算法在对N个数据进行排序时,无论原数组有无顺序,都需要进行N-1步的排序。
优点:在数组已有一定顺序的情况下,排序效率较好。
缺点:如果数据无规则,则需要移动大量的数据。其排序效率也不是很好。
效率:时间复杂度O(n^2),并且是一个稳定的排序方法。
直接插入排序,平均O(n^2),最坏O(n^2),空间O(1),稳定性
(3)直接插入排序代码
public class shuzuA {
public static void main(String[] args){
int[] shuzu={1,234,42,344,5,3,9};
insertionSort(shuzu);
for(int i=0;i<shuzu.length;i++){
System.out.print(" "+shuzu[i]);
}
}
public static void insertionSort(int[] a){
int i;
int j;//需要插入的位置
int t;//要插入的数据
int h;
for(i=1;i<a.length;i++){
t=a[i];//要插入的数据是a[i],新抓的牌
j=i-1;//使需要插入的位置的在需要插入的元素的前一个
while(j>=0&&t<a[j]){
a[j+1]=a[j];
j--;
}
a[j+1]=t; //将数据t插入到正确的位置。
}
}
}
3:Shell排序(希尔排序/缩小增量排序)
(1)shell排序的流程
——(1)将有n个元素的数组分为n/2个数字序列,第1个数据和第n/2+1个数据为一对,......
——(2)一次循环是每一个序列对排好顺序
——(3)然后,在变为n/4个序列,在次排序
——(4)不断重复上述过程,随着序列减少最后变为一个,也就完成了整个排序。
(2)shell排序的分析
shell排序的时间复杂度是一个复杂的问题,因为shell排序的时间复杂度与步长序列有关。
(3)shell排序的代码
public class shuzuA {
public static void main(String[] args){
int[] shuzu={1,4,5,7,3,8,9,2};
System.out.print("原数组为");
for(int h=0;h<shuzu.length;h++){
System.out.print(" "+shuzu[h]);
}
System.out.println();
shellSort(shuzu);
}
public static void shellSort(int[] a){
int i,j;
int r,temp;//r为间距
int x=0;
for(r=a.length/2;r>=1;r/=2){//将数组元素分为多个数字序列
for(i=r;i<a.length;i++){
temp=a[i];
j=i-r;
while(j>=0&&temp<a[j]){
a[j+r]=a[j];
j-=r;
}
a[j+r]=temp;
}
x++;
System.out.print("第"+x+"步排序结果");
for(int h=0;h<a.length;h++){
System.out.print(" "+a[h]);
}
System.out.println();
}
}
}
四:合并排序(MergeSort)
(1)合并排序的流程(通过多次的二路合并完成一遍的合并)
——(1)将N个原始数据看成N个长度为1的有序字表,这时妹子字表中只有一个元素,
将他们一次两两合并,得到长度为2的若干有序字表
——(2)经过第1次合并,得到长度为2的有序表序列,在将长度为2的有序表序列进行两
两合并。得到长度为4的有序字表
——(3)不断重复,一直到最后得到长度为N的有序字表,从而完成需过程。
(2)合并排序分析
合并排序,平均O(nlogn),最坏O(nlogn),空间O(n),稳定
(4)合并排序的代码
public class DemoJoin{
static final int SIZE=15;
static void mergeOne(int a[],int b[],int n,int len)
{
int i,j,k,s,e;
s=0;
while(s+len<n)
{
e=s+2*len-1;
if(e>=n)
e=n-1;
//相邻有序段合并
k=s;
i=s;
j=s+len;
while(i<s+len&&j<=e)
{
if(a[i]<=a[j])
b[k++]=a[i++];
else
b[k++]=a[j++];
}
while(i<s+len){
b[k++]=a[i++];
}
while(j<=e)
b[k++]=a[j++];
s=e+1;
}
if(s<n)
{
for(;s<n;s++)
b[s]=a[s];
}
}
static void mergeSort(int a[],int n){
int h,count,len,f;
count=0;
len=1;
f=0;
int[] p=new int[n];
while(len<n){
if(f==1)
mergeOne(p,a,n,len);
else
mergeOne(a,p,n,len);
len=len*2;
f=1-f;
count++;
System.out.printf("第"+count+"步排序结果");
for(h=0;h<SIZE;h++){
System.out.printf(" "+a[h]);
}
System.out.println();
}
if(f==1){
for(h=0;h<n;h++){
a[h]=p[h];
}
}
}
public static void main(String[] args) {
int[] shuzu=new int[SIZE];
int i;
for(i=0;i<SIZE;i++){
shuzu[i]=(int)(100+Math.random()*(100+1));
}
System.out.println("排序前的数组:");
for(i=0;i<SIZE;i++){
System.out.print(shuzu[i]+" ");
}
System.out.println();
mergeSort(shuzu,SIZE);
System.out.println("排序后的数组:");
for(i=0;i<SIZE;i++){
System.out.print(shuzu[i]+" ");
}
System.out.println();
}
}