基础算法
各个算法的复杂度及稳定性等
冒泡排序(蛮力法)
理解
首先,先理解什么是冒泡排序。
冒泡排序是属于快速排序中简单的算法,顾名思义,类似于泡泡向上浮动,至于最后大的在前面还是在后面由自己决定。
函数代码
这里使用的冒泡排序是通过蛮力法实现的,函数展示如下:
public void BulleSort(int r[],int n) {
int bound,exchange=n-1;
while(exchange!=0)
{
bound=exchange;exchange=0;
for(int i=0;i<bound;i++)
{
if(r[i+1]<r[i])
{
int temp=r[i];
r[i]=r[i+1];
r[i+1]=temp;
//只要交换了,那一定是后面的,有可能一趟排好多个,比如第二躺直接55、65都拍好了
exchange=i;
}
}
}
}
这里如果用用两个for的话总共要进行n-1躺,但用while可以不用进行那么多次,其中两个for,第一个是躺数,第二个是比较相邻位置。
测试用例
使用的测试用例:
int r[]= {50,13,55,97,27,38,49,65};
int n=r.length;
sortAlogrithm bs = new sortAlogrithm();
bs.BulleSort(r, n);
选择排序(蛮力法)
理解
这里主要说的是简单选择排序,它属于选择排序中(还包括树形选择排序和堆排序):
简单选择排序就是每次排序都将其中最小(大)的数值选择出来,放到前面,最后就是有序的。
函数代码
使用的函数代码如下:
public static void SelectSort(int r[],int n)
{
int index;
for(int i=0;i<n-1;i++)
{
index=i;
for(int j=i+1;j<n;j++)
{
if (r[j]<r[index])
index=j;
}
if (index!=i)
{
int temp=r[i];
r[i]=r[index];
r[index]=temp;
}
}
}
第一个for循环是总的比较次数,第二个是将当前的和后面的每个对比大小,比后面的大就交换,最后将最小的放到前面。
测试用例
测试用例:
int r[] = {49,27,65,76,38,13};
int n = r.length;
SelectSort(r,n);
归并排序(分治法)
理解
归并排序又是另一种排序算法,这里主要讲述2路归并排序。
将给定的数值分成两部分,两两分开对比,最后合并。
函数代码
函数代码:
public static void Merge(int r[],int r1[],int s,int m,int t)//合并子序列
{
int i=s,j=m+1,k=s;
while(i<=m && j<=t) {
if(r[i] <= r[j]) r1[k++] = r[i++]; //小的放进r1中
else r1[k++] = r[j++];
}
while (i<=m) r1[k++] = r[i++]; //左边没排完
while (j<=t) r1[k++] = r[j++]; //右边没排完
}
public static void MergeSort(int r[],int s,int t)//进行分组
{
int m;
int r1[]=new int[r.length]; //r1用来装有序的数组
if(s==t) return; //如果相等就返回
else{
m=(s+t)/2;
MergeSort(r,s,m);
MergeSort(r,m+1,t);
Merge(r,r1,s,m,t);
for (int i=s;i<=t;i++) {
r[i]=r1[i];
}
}
}
测试用例
测试用例:
int r[] = {8,3,2,6,7,1,5,4};
int s=0,n=r.length;
MergeSort(r,s,r.length-1);
快速排序 (分治法)
理解
快速排序就是通过将最开始的数和最后面的一个开始对比,如果比最后一个小则和倒数第二个对比,以此类推,找到比选定的第一个数小的值,就将其放到第一个,然后从头开始找,找到比选定值大的,将其放到之前找到小的数值那里,从刚发的那个位置前一个,又从头往后找,最终,第一次对比结束后,排在选的值前面的都是比它小的,在它后面的都是比它大的,由此,就完成了初步划分,之后,对两边重复之前的操作。最后就得到了有序数列。
函数代码
public static int Partition(int r[],int first,int end)
{
int i=first,j=end;
while (i<j) {
while(i<j && r[i] <= r[j])j--;
if (i<j)
{
int temp=r[i];
r[i]=r[j];
r[j]=temp;
i++;
}
while(i<j && r[i] <= r[j])i++;
if (i<j)
{
int temp=r[i];
r[i]=r[j];
r[j]=temp;
j--;
}
}
return i;
}
public static void QuickSort(int r[],int first,int end)
{
int privot;
if (first < end)
{
privot=Partition(r,first,end);
QuickSort(r,first,privot);
QuickSort(r,privot+1,end);
}
}
测试用例
int r[]= {23,13,35,6,19,50,28};
int n=r.length;
QuickSort(r,0,r.length-1);
插入排序(减治法)
理解
插入排序可以分为直接插入排序、其它插入排序(折半插入排序、2-路插入排序、表插入排序 )和希尔排序。这里讲述的是直接插入排序,使用的是减治法(堆排序也是减治法)。
主要就是将选定的一个数作为“哨兵”,让它和前面的数进行大小对比,从前面最后一个数往前对比,小于前面的数就将前面的数往后移,大于前面的数就放在当前位置,下一个数作为“哨兵”重复之前的操作。于是,前面的都是有序的,后面的都是无序的,最后全部有序。(这里为了防止溢出,我将数组的第一位作为“哨兵”位,给定了一个0值,这样其实会有其他影响。)
函数代码
public static void InsertSort(int r[],int n)
{
for(int i=2;i<n;i++)
{
int j=i-1;
r[0]=r[i];
for (;r[0]<r[j];j--)
r[j+1]=r[j]; //记录后移
r[j+1]=r[0];
}
}
测试用例
int r[] = {0,12,15,9,20,10,6};
InsertSort(r,r.length);
for(int i=1;i<r.length;i++)
System.out.print(r[i]+" ");
希尔排序
理解
希尔排序主要在于选定一个好的增量,基本思想是先将整个待排序数列分割成若干个子序列分别进行直接插入排序,待整个序列基本有序再对整体进行插入排序。
对插入算法进行修改
希尔排序算法描述:
对增量的选择:
代码以后有缘补。