1.插入排序
插入排序的基本思想是:每一步将一个待排序元素按其关键字值得大小插入到已排序序列得适当位置上,直到待排序元素插入完为止.如果要对具有n个元素得数组arr进行排序,初始状态时,可以认为已排序序列为arr[0],待排序序列为arr[1]~arr[n-1],从arr[i]开始向arr[0]方向扫描各元素,寻找适当位置插入arr[i],依次进行,即可完成排序.
public class Insertion_Sort {
public static int[] Insert_Sort(int[] arr) {
int len = arr.length;
int preIndex,current;
for (int i = 1;i < len;i++) {
preIndex = i-1;
current = arr[i];
while (preIndex >= 0 && arr[preIndex] > current) {
arr[preIndex+1] = arr[preIndex];
preIndex--;
}
arr[preIndex+1]=current;
}
return arr;
}
public static void main(String args[]) {
int[] arr = {3,38,44,5,47,15,36,26,27,2,46,4,19,50,48};
int[] ans = Insert_Sort(arr);
for (int i : ans){
System.out.println(i);
}
}
}
2.选择排序
选择排序思想是:每次从待排序序列中选择一个关键字最小的元素(当需要按关键字升序排列时),顺序排在已排序序列的最后,直至全部排完.而选择排序方法中最简的就是直接选择排序,就是通过顺序比较找出待排序序列中的最小元素.
public class select_sort {
public static int[] select_sort(int[] arr) {
int len = arr.length;
int minIndex,temp;
for(int i = 0;i<len-1;i++) {
minIndex = i;
for (int j = i+1;j<len;j++) {
if(arr[j]<arr[minIndex]) {
minIndex = j;
}
}
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
public static void main(String args[]) {
int[] arr = {3,38,44,5,47,15,36,26,27,2,46,4,19,50,48};
int[] ans = select_sort(arr);
for (int i : ans){
System.out.println(i);
}
}
}
3.希尔排序
public class ShellSort {
public static void main(String []args){
int []arr ={1,4,2,7,9,8,3,6};
sort(arr);
System.out.println(Arrays.toString(arr));
int []arr1 ={1,4,2,7,9,8,3,6};
sort1(arr1);
System.out.println(Arrays.toString(arr1));
}
public static void sort(int []arr){
//增量gap,并逐步缩小增量
for(int gap=arr.length/2;gap>0;gap/=2){
//从第gap个元素,逐个对其所在组进行直接插入排序操作
for(int i=gap;i<arr.length;i++){
int j = i;
while(j-gap>=0 && arr[j]<arr[j-gap]){
//插入排序采用交换法
swap(arr,j,j-gap);
j-=gap;
}
}
}
}
public static void sort1(int []arr){
//增量gap,并逐步缩小增量
for(int gap=arr.length/2;gap>0;gap/=2){
//从第gap个元素,逐个对其所在组进行直接插入排序操作
for(int i=gap;i<arr.length;i++){
int j = i;
int temp = arr[j];
if(arr[j]<arr[j-gap]){
while(j-gap>=0 && temp<arr[j-gap]){
//移动法
arr[j] = arr[j-gap];
j-=gap;
}
arr[j] = temp;
}
}
}
}
public static void swap(int []arr,int a,int b){
arr[a] = arr[a]+arr[b];
arr[b] = arr[a]-arr[b];
arr[a] = arr[a]-arr[b];
}
}
4.堆排序
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法.堆积是一个近似完全二叉树的结构,是一种选择排序.它的最好,最坏,平均时间复杂度均为O(nlogn),它也是不稳定排序.并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点,堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:
大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列
小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列.
public class HeapSort {
public static void sort(int[] arr){
//1.构建大顶堆
for(int i =arr.length/2-1;i>=0;i--){
//从第一个非叶子节点从上到下,从由到左调整结构
adjustHeap(arr,i,arr.length);
}
//2.调整堆结构+交换堆顶元素与末尾元素
for(int j =arr.length-1;j>0;j--){
swap(arr,0,j);//将堆顶元素与末尾元素进行交换
adjustHeap(arr,0,j);//重新对堆进行调整
}
}
/**
*调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上)
*/
public static void adjustHeap(int[]arr,int i,int length){
int temp=arr[i];//先取出当前元素
for(int k=i*2+1;k<length;k=k*2+1){//从i节点的左子树开始,也就是2i+1开始
if(k+1<length && arr[k]<arr[k+1]){//如果左子节点小于右子节点,k指向右子节点
k++;
}
if(arr[k]>temp){//如果子节点大于父节点,将子节点赋值给父节点(不用进行交换)
arr[i]=arr[k];
i=k;
}else{
break;
}
}
arr[i]=temp;//将temp放到最终的位置
}
/**
* 交换元素
*/
public static void swap(int[]arr,int a,int b){
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
public static void main(String args[]){
int[] arr ={4,6,8,5,9};
sort(arr);
System.out.println(Arrays.toString(arr));
}
}
5.冒泡排序
基本思想是:
(1)对具有n个元素的序列按升序进行冒泡排序,首先将第一个元素与第二个元素进行比较,若为逆序,则将两元素交换.然后比较第二、第三个元素,以此类推,直到第n-1和第n个元素进行比较和交换.此过程为第一趟起泡排序.经过第一趟最大的元素便被交换到了第n的位置.
(2)对前n-1个元素进行第二趟起泡排序,将其中最大元素交换到第n-1个位置.
(3)如此继续,直到某一趟排序未发生任何交换时,排序完毕。对n个元素的序列,起泡排序最多需要n-1趟。在这个排序过程中小的气泡往上浮,大的气泡往下沉,就像冒泡一样,因此称为冒泡排序。
public class bubble_sort {
public int[] bubble_sort(int[] arr) {
for (int i = 0;i< arr.length;i++) { //计数
for (int j = 0;j<arr.length-1-i;j++) {
if (arr[j] > arr[i]) { //相邻元素两两对比
int temp = arr[j+1]; //元素交换
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
}
6.快速排序
快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
public class QuickSort {
public static int[] quicksort(int[]arr,int left,int right){
int i,j,t,temp;
if(left>right) return arr;
temp=arr[left];
i=left;
j=right;
while(i != j) {
while(arr[j]>=temp && i<j){
j--;
}
while(arr[i]<=temp && i<j){
i++;
}
if(i<j){
t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
arr[left]=arr[i];
arr[i]=temp;
quicksort(arr,left,i-1);
quicksort(arr,i+1,right);
return arr;
}
public static void main(String args[]) {
int[] arr = {6,1,2,7,9,3,4,5,10,8};
int left=0;
int right=arr.length-1;
int[] ans = quicksort(arr,left,right);
for (int i : ans){
System.out.println(i);
}
}
}
7.归并排序
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用,将已有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并.
package sort_algorithm;
import java.util.Arrays;
public class merge_sort {
public static int[] merge_Sort(int[] sourceArray) {
// 对arr进行拷贝,不改变参数内容
int[] arr = Arrays.copyOf(sourceArray,sourceArray.length);
if(arr.length < 2) return arr;
int middle= (int) Math.floor(arr.length/2);
int[] left = Arrays.copyOfRange(arr,0,middle);//左子序列
int[] right= Arrays.copyOfRange(arr,middle,arr.length);//右子序列
return merge(merge_Sort(left),merge_Sort(right));
}
public static int[] merge(int[] left,int[] right) {
int result[]=new int[left.length+right.length];
int i = 0;
while(left.length>0 && right.length>0) {
if(left[0]<=right[0]){
result[i++]=left[0];
left=Arrays.copyOfRange(left,1,left.length);
}else{
result[i++]=right[0];
right=Arrays.copyOfRange(right,1,right.length);
}
}
while(left.length>0){
result[i++]=left[0];
left=Arrays.copyOfRange(left,1,left.length);
}
while(right.length>0){
result[i++]=right[0];
right=Arrays.copyOfRange(right,1,right.length);
}
return result;
}
public static void main(String args[]) {
int[] arr = {3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};
int[] ans = merge_Sort(arr);
for (int i : ans){
System.out.println(i);
}
}
}