常见的排序算法
本文采取的排序均按照从小到大排
插入排序
主要由两个部分组成,(1)将大数后移(2)将空出的位置进行赋值
private static int[] sort(int[] array) {
for (int i = 1; i < array.length; i++) {
int temp = array[i];
int j = i - 1;
while(j>=0&&array[j]>temp) {
array[j+1] = array[j];//向左遍历,寻找比自己大的,并将大的数后移
j--;
}
array[j+1] = temp;//将后移后多出来的位置留给自己,若未发生移动则在自己的位置上赋自己的值
}
return array;
}
希尔排序
插入排序改改就行,相当于多了一个步长
private static int[] sort(int[] array) {
int [] keys = new int [] {5,3,1};
for (int m = 0; m < keys.length; m++) {
int key = keys[m];
for (int i = 1 * keys[m]; i < array.length; i+=key) {
int temp = array[i];
int j = i - key;
while(j>=0&&array[j]>temp) {
array[j+key] = array[j];//向左遍历,寻找比自己大的,并将大的数后移
j-=key;
}
array[j+key] = temp;//将后移后多出来的位置留给自己,若未发生移动则在自己的位置上赋自己的值
}
}
return array;
}
冒泡排序
将左右两个数进行比较,如果左边大于右边,则进行交换,一轮做完后,会将次轮中最大的数移动到最右边,下次遍历时就可以不必遍历到最后
private static int[] sort(int[] array) {
for (int i = 0; i < array.length; i++) {
for (int j = 1; j < array.length-i; j++) {//右边已经排好序,可以不遍历到array.length
if(array[j]<array[j-1]) {//左边大于右边,则进行交换
int temp = array[j];
array[j] = array[j-1];
array[j-1] = temp;
}
}
}
return array;
}
选择排序
最简单的排序,选出最小的数的下标然后交换即可
private static int[] sort(int[] array) {
int pos = 0;
for (int i = 0; i < array.length; i++) {
for (int j = i; j < array.length; j++) {
if(array[pos] > array[j]) {
pos = j;
}
}
int temp = array[pos];
array[pos] = array[i];
array[i] = temp;
pos = i+1;
}
return array;
}
快速排序
选择基准值,其左边的数均比基准值小,右边的数都比基准值大,然后递归缩小范围
private static void sort(int[] array,int low ,int high) {
int l = low;
int h = high;
int key = array[l];
while(l<h) {
//先从右边开始,选出比基准值小的数然后与左边进行交换
while(l<h&&key<=array[h]) {
h--;
}
if(l<h) {//采用交换法
int temp = array[l];
array[l] = array[h];
array[h] = temp;
}
//再从左边开始,选出比基准值大的数然后与右边进行交换
while(l<h&&key>=array[l]) {
l++;
}
if(l<h) {
int temp = array[l];
array[l] = array[h];
array[h] = temp;
}
}
//递归调用,进行分割
if(low<l-1) {
sort(array,low,l-1);
}
if(high>l+1) {
sort(array,l+1,high);
}
}
归并排序
将数组进行划分,然后一边根据大小合并,一边排序
/**
* 分解+合并
*
* @param arr 需要排序的数组
* @param left 起点
* @param right 终点
*/
private static void mergeSort(int[] arr, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
mergeSort(arr, left, mid );
mergeSort(arr, mid+1, right);
merge(arr, left, mid, right);
}
}
/**
* 合并
*
* @param arr 原数组
* @param left 左段起点
* @param mid 两段的分割点
* @param right 右端的终点
*/
private static int[] merge(int[] arr, int left, int mid, int right) {
int[] temp = new int[arr.length+1];
int pos = mid+1;
int tPos = 0;
int tl = left;
// 遍历arr的左右两段存入temp
while (left <= mid && pos <= right) {
if (arr[left] < arr[pos]) {
temp[tPos++] = arr[left++];
} else {
temp[tPos++] = arr[pos++];
}
}
// 右段已经结束,遍历左段
if (pos >= right) {
while (left <= mid) {
temp[tPos++] = arr[left++];
}
}
// 左段已经结束,遍历右段
if (left >= mid) {
while (pos <= right) {
temp[tPos++] = arr[pos++];}}
//将temp赋到原数组
int t = 0;
int tempLeft = tl;
while (tempLeft <= right) {
arr[tempLeft++] = temp[t++];
}
return temp;
}
基数排序
基数排序通过键值的各个位的值,将要排序的元素分配至某些“桶”中,达到排序的作用
private static void radixSort(int[] arr) {
int maxLength = getMaxLength(arr);
int[][] bucket = new int[10][10];
int[] bucketCounts = new int[10];
//依据所有数字中最长位的大小进行循环
for (int m = 0,basic = 1; m < maxLength; m++,basic *= 10) {
//根据某一位大小,将数字先挂到bucket中
for (int i = 0; i < arr.length; i++ ) {
int key = arr[i] / basic % 10;
bucket[key][bucketCounts[key]] = arr[i];
bucketCounts[key]++;
}
//将bucket中的数字依次取出,完成一轮排序
int pos = 0;
for (int index = 0; index < bucketCounts.length; index++) {
if (bucketCounts[index] != 0) {
for (int i=0;i<bucketCounts[index];i++) {
arr[pos++] = bucket[index][i];
}
}
}
//初始化bucketCounts为0,方便进行下一步bucket挂载和取出
for (int i = 0; i < bucketCounts.length; i++) {
bucketCounts[i] = 0;
}
}
}
二叉树排序
将数字取出放入一颗"树"中,该“树”左小右大
public class MyTest {
public static void main(String[] args) {
int []nums = new int[] {45,65,-8,75,5,61,1};
Node root = new Node(nums[0]);
for (int i = 1; i < nums.length; i++) {
root.add(new Node(nums[i]));
}
root.printNodes();
}
}
class Node{
Node left;
Node right;
int value;
public Node(int value) {
super();
this.value = value;
}
//添加一个节点
public void add(Node temNode) {
if(this.value>temNode.value) {//左小右边大于等于
if(this.left==null) {
this.left = temNode;
}else {
this.left.add(temNode);//让左边的节点去添加新的节点
}
}else {
if(this.right==null) {
this.right = temNode;
}else {
this.right.add(temNode);//让右边的节点去添加新的节点
}
}
}
//中序遍历
public void printNodes() {
if(this.left != null) {
this.left.printNodes();
}
System.out.print(this.value+"\t");
if(this.right != null) {
this.right.printNodes();
}
}
}