八大排序算法
一、归并排序
递归及非递归的JAVA实现
public static void MergeSort(int[] arr, int low, int high)
{
//使用递归的方式进行归并排序,所需要的空间复杂度是O(N+logN)
int mid = (low + high)/2;
if(low < high)
{
//递归地对左右两边进行排序
MergeSort(arr, low, mid);
MergeSort(arr, mid+1, high);
//合并
merge(arr, low, mid, high);
}
}
//merge函数实际上是将两个有序数组合并成一个有序数组
//因为数组有序,合并很简单,只要维护几个指针就可以了
private static void merge(int[] arr, int low, int mid, int high)
{
//temp数组用于暂存合并的结果
int[] temp = new int[high - low + 1];
//左半边的指针
int i = low;
//右半边的指针
int j = mid+1;
//合并后数组的指针
int k = 0;
//将记录由小到大地放进temp数组
for(; i <= mid && j <= high; k++)
{
if(arr[i] < arr[j])
temp[k] = arr[i++];
else
temp[k] = arr[j++];
}
//接下来两个while循环是为了将剩余的(比另一边多出来的个数)放到temp数组中
while(i <= mid)
temp[k++] = arr[i++];
while(j <= high)
temp[k++] = arr[j++];
//将temp数组中的元素写入到待排数组中
for(int l = 0; l < temp.length; l++)
arr[low + l] = temp[l];
}
二、快速排序
快排算法JAVA实现
/**
* 快速排序
* 基本思想:
* 1.在待排序的元素任取一个元素作为基准(通常选第一个元素,但最佳选择方法是从待排序元素中随机选取一个作为基准),称为基准元素;
* 2.将待排序的元素进行分区,比基准元素大的元素放在它的右边,比其小的放在它的左边;
* 3.对左右两个分区重复以上步骤直到所有元素都是有序的。
*/
public void quick_sort(int[] arr,int _left,int _right){
int left=_left;
int right=_right;
int temp=0;
//待排序元素至少有1个
if(left<=right){
temp=arr[left]; //待排序的第一个元素作为基准元素
while(left!=right){ //从左右两边交替扫描,直到left = right
while(right>left && arr[right]>=temp)
right--; //从右往左扫描,找到第一个比基准元素小的元素
arr[left]=arr[right]; //找到这种元素arr[right]后与arr[left]交换
while(left<right && arr[left]<=temp)
left++; //从左往右扫描,找到第一个比基准元素大的元素
arr[right]=arr[left]; //找到这种元素arr[left]后,与arr[right]交换
}
arr[right]=temp; // 基准元素归位
quick_sort(arr,_left,left-1); //对基准元素左边的元素进行递归排序
quick_sort(arr,right+1,_right); //对基准元素右边的进行递归排序
}
}
三、堆排序
堆排序
堆排序算法JAVA实现
/**
* 堆排序
* 基本思想:
* 首先,堆分为最大堆和最小堆,最大堆则是指在一棵树中,父结点总是比子结点大,堆顶是整棵树中的最大值,
* 同样的最小堆则是父结点都比子结点要小,堆顶则是最小值。
*
* 排序的过程则是将数组根据要排列的顺序去决定是排最大堆还是最小堆,建完堆以后将堆顶的值取出后,
* 重新将堆进行调整,调整后的值同样满足堆的性质,接着再取出,以此类推。
*/
/**
* (最大)堆的向下调整算法
* 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
* 其中,N为数组下标索引值,如数组中第1个数对应的N为0。
* @param arr
* @param start
* @param end
*/
public void maxHeapDown(int[] arr,int start,int end){
int current=start; //当前节点位置,即父亲节点
int left=2*current+1; //左孩子的位置
while(left<=end){ //子节点在范围内才进行调整
//选择子节点中大的值
if(left+1<=end && arr[left]<arr[left+1])
left++;
if(arr[current]>arr[left])
break; //调整结束
else{ //否则继续和孙节点进行比较
swap(arr,current,left);
current=left;
left=2*current+1;
}
}
}
public void heap_sort(int[] arr,int len){
//初始化,从i最后一个父亲节点开始调整
for(int i=len/2-1;i>=0;i--)
maxHeapDown(arr,i,len-1);
//先将第一个元素和后面的元素进行交换,再调整
for(int i=len-1;i>0;i--){
swap(arr,0,i);
maxHeapDown(arr,0,i-1);
}
}
四、冒泡排序
冒泡排序算法JAVA实现
/**
* 冒泡排序
* 基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,
* 让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
* @param arr
* @param len
*/
public void bubble_sort(int[] arr,int len){
//躺数
for(int i=0;i<len-1;i++){
for(int j=0;j<len-1-i;j++){
if(arr[j]>arr[j+1]){
swap(arr,j,j+1);
}
}
}
}
五、直接插入排序
直接插入排序算法JAVA实现
/**
* 直接插入排序
* 基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。
* 设数组为arr[0…n-1]。
* 1.初始时,arr[0]自成1个有序区,无序区为arr[1..n-1]。令i=1
* 2.将arr[i]并入当前的有序区arr[0…i-1]中形成arr[0…i]的有序区间。
* 3.i++并重复第二步直到i==n-1。排序完成。
* @param arr
* @param len
*/
public void insert_sort(int[] arr,int len){
int i,j;
for(i=1;i<len;i++){
//如果arr[i]>arr[i-1],无需调整
if(arr[i]<arr[i-1]){
int temp=arr[i];
//为arr[i]找位置,找到第一个比arr[i]小的元素,然后把arr[i]放在其后即可
for(j=i-1;j>=0&&arr[j]>temp;j--){
arr[j+1]=arr[j]; //移动
}
arr[j+1]=temp;
}
}
}
六、简单选择排序
/**
* 简单选择排序
* 基本思想:
* 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,
* 然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
* @param arr
* @param len
*/
public void select_sort(int[] arr,int len){
for(int i=0;i<len-1;i++){
int min=i;
for(int j=i+1;j<len;j++){
if(arr[j]<arr[min])
min=j;
}
swap(arr,i,min);
}
}
七、排序算法比较