您的位置:首页 > 编程语言 > Go语言

【algorithm】排序算法

2017-09-04 17:52 351 查看
交换排序

|–冒泡排序

|–快速排序

插入排序

|–直接插入排序

|–希尔排序

选择排序

|–简单选择排序

|–堆排序

归并排序

基数排序



稳定排序:假设在待排序的文件中,存在了两个或两个以上的记录具有相同的关键字,在某种排序算法排序后,若这些相同关键字的元素的相对次序依然不变,则这种排序方法是稳定的。

稳定:冒泡、插入、归并、基数

不稳定:选择、快速、希尔、堆

public static void main(String[] args) {
int[] arr = {3,9,7,6,8,4,5,10,2,1};
for (int i : arr) {
System.out.print(i+" ");
}
System.out.println();
//bubbleSort(arr);
//quickSort(arr, 0, arr.length-1);
//insertSort(arr);
//shellSort(arr);
//selectSort(arr);
heapSort(arr, arr.length);
//int[] merge = new int[10];
//mergeSort(arr, merge, 0, arr.length-1);
//basketSort(arr);
for (int i : arr) {
System.out.print(i+" ");
}
System.out.println();
}

public static void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}


冒泡

/*
冒泡排序
最好时间复杂度 o(n),最坏时间复杂度o(n^2),平均o(n^2),稳定
*/
public static void bubbleSort(int[] arr){
if (arr == null || arr.length == 0) {
return;
}
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-1-i; j++) {
if (arr[j] > arr[j+1]) {
swap(arr,j,j+1);
}
}
}
}


每趟排序结果:

start : 3 9 7 6 8 4 5 10 2 1
process: 3 7 6 8 4 5 9 2 1 10
process: 3 6 7 4 5 8 2 1 9 10
process: 3 6 4 5 7 2 1 8 9 10
process: 3 4 5 6 2 1 7 8 9 10
process: 3 4 5 2 1 6 7 8 9 10
process: 3 4 2 1 5 6 7 8 9 10
process: 3 2 1 4 5 6 7 8 9 10
process: 2 1 3 4 5 6 7 8 9 10
process: 1 2 3 4 5 6 7 8 9 10
end  : 1 2 3 4 5 6 7 8 9 10


快排

/*
* 快速排序
* 最好时间复杂度 o(nlog(2)n),最坏时间复杂度o(n^2),平均o(n^2),不稳定
*/
public static void quickSort(int[] arr,int left,int right){
//左边索引小于右边,则还未排序完成  
if (left < right) {
//取中间的元素作为比较基准,小于他的往左边移,大于他的往右边移
int mid = arr[(left+right)/2];
int i = left - 1;
int j = right + 1;
while (true) {
//移动下标,左边的往右移动,右边的向左移动
while(arr[++i] < mid && i < right);
while(arr[--j] > mid && j > left);
if (i >= j) break;
swap(arr, i, j);
}
quickSort(arr, left, i-1);
quickSort(arr, j+1, right);
}
}


每趟排序结果:

start : 3 9 7 6 8 4 5 10 2 1
process: 3 1 7 6 2 4 5 10 8 9
process: 3 1 5 4 2 6 7 10 8 9
process: 3 1 2 4 5 6 7 10 8 9
process: 1 3 2 4 5 6 7 10 8 9
process: 1 2 3 4 5 6 7 10 8 9
process: 1 2 3 4 5 6 7 10 8 9
process: 1 2 3 4 5 6 7 10 8 9
process: 1 2 3 4 5 6 7 8 10 9
process: 1 2 3 4 5 6 7 8 9 10
end  : 1 2 3 4 5 6 7 8 9 10


插入排序

/*
* 直接插入排序
* 最好时间复杂度o(1),最坏时间复杂度o(n^2),平均o(n^2),稳定
*/
public static void insertSort(int[] arr){
//直接插入排序是将待比较的数值与它的前一个数值进行比较,所以外层循环是从第二个数值开始的
for (int i = 1; i < arr.length; i++) {
if (arr[i] < arr[i-1]) {
//用一个变量来保存当前待比较的数值,因为当一趟比较完成时,我们要将待比较数值置入比它小的数值的后一位
int temp = arr[i];
int j = 0;
for(j = i-1;j >= 0 && temp < arr[j];j--)
arr[j+1] = arr[j];
arr[j+1] = temp;
}
}
}


每趟排序结果:

start : 3 9 7 6 8 4 5 10 2 1
process: 3 9 7 6 8 4 5 10 2 1
process: 3 7 9 6 8 4 5 10 2 1
process: 3 6 7 9 8 4 5 10 2 1
process: 3 6 7 8 9 4 5 10 2 1
process: 3 4 6 7 8 9 5 10 2 1
process: 3 4 5 6 7 8 9 10 2 1
process: 3 4 5 6 7 8 9 10 2 1
process: 2 3 4 5 6 7 8 9 10 1
process: 1 2 3 4 5 6 7 8 9 10
end  : 1 2 3 4 5 6 7 8 9 10


希尔排序

/* *
* 希尔排序
* 最好时间复杂度o(n),最坏时间复杂度o(n^2),平均o(n^1.3),不稳定
*/
public static void shellSort(int[] arr){
int len = arr.length;
for (int h = len/2; h > 0; h = h / 2) {
for(int i = h; i < len; i++){
for (int j = i-h; j > 0 && arr[j] > arr[j + h]; j -= h) {
swap(arr, j, j + h);
}
}
}
}


每趟排序之后:

start : 3 9 7 6 8 4 5 10 2 1
process: 3 5 7 2 1 4 9 10 6 8
process: 3 2 1 4 6 5 7 8 9 10
process: 3 1 2 4 5 6 7 8 9 10
end  : 3 1 2 4 5 6 7 8 9 10


选择排序

/*
* 简单选择排序
* 最好时间复杂度o(n^2),最坏时间复杂度o(n^2),平均o(n^2),不稳定
*/
public static void selectSort(int[] arr){
int min = 0;
for (int i = 0; i < arr.length; i++) {
min = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[min] > arr[j]) {
min = j;
}
}
if (min != i) {
swap(arr, min, i);
}
}
}


每趟排序之后:

start : 3 9 7 6 8 4 5 10 2 1
process: 1 9 7 6 8 4 5 10 2 3
process: 1 2 7 6 8 4 5 10 9 3
process: 1 2 3 6 8 4 5 10 9 7
process: 1 2 3 4 8 6 5 10 9 7
process: 1 2 3 4 5 6 8 10 9 7
process: 1 2 3 4 5 6 8 10 9 7
process: 1 2 3 4 5 6 7 10 9 8
process: 1 2 3 4 5 6 7 8 9 10
process: 1 2 3 4 5 6 7 8 9 10
process: 1 2 3 4 5 6 7 8 9 10
end  : 1 2 3 4 5 6 7 8 9 10


堆排序

/*
* 堆排序
*/
public static void heapSort(int[] arr,int top){
//建一个初始的大根堆
for (int i = arr.length / 2 - 1; i >= 0; i--) {
heapAdjust(arr,i,arr.length);
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "  ");
}
System.out.println();
for (int i = arr.length - 1; i >= arr.length - top; i--){
swap(arr, 0, i);
heapAdjust(arr, 0, i);
}
}
private static void heapAdjust(int[] arr,int parent,int len){
int temp = arr[parent];
//左结点
int child = 2*parent + 1;
while (child < len) {
//找出两个子结点中较大的一个
if (child + 1 < len && arr[child] < arr[child + 1])
child++;
//如果父节点大于子结点中较大的一个,退出。
if(temp >= arr[child]) break;
//将比子结点大的值赋值给父结点
arr[parent] = arr[child];
parent = child;
child = 2 * parent + 1;
}
arr[parent] = temp;
}


每趟排序之后:

start : 3 9 7 6 8 4 5 10 2 1
initheap:10 9 7 6 8 4 5 3 2 1
process: 9 8 7 6 1 4 5 3 2 10
process: 8 6 7 3 1 4 5 2 9 10
process: 7 6 5 3 1 4 2 8 9 10
process: 6 3 5 2 1 4 7 8 9 10
process: 5 3 4 2 1 6 7 8 9 10
process: 4 3 1 2 5 6 7 8 9 10
process: 3 2 1 4 5 6 7 8 9 10
process: 2 1 3 4 5 6 7 8 9 10
process: 1 2 3 4 5 6 7 8 9 10
process: 1 2 3 4 5 6 7 8 9 10
end  : 1 2 3 4 5 6 7 8 9 10


归并排序

/*
* 归并排序
* 算法规则:
* 1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
* 2.设定两个指针,最初位置分别为两个已经排序序列的起始位置
* 3.比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
* 4.重复步骤3直到某一指针到达序列尾
* 5.将另一序列剩下的所有元素直接复制到合并序列尾
*/
public static void mergeSort(int[] arr,int[] merge,int first,int last){
if (first >= last) return;
int mid = (last + first) >> 1;
mergeSort(arr, merge, first, mid);
mergeSort(arr, merge, mid + 1, last);
merger(arr, merge, first,last,mid);
}
private static void merger(int[] arr, int[] merge, int first, int last,int mid)
{
System.out.print("first:"+first+",last:"+last+",mid:"+mid+" : ");
int i = first;
int j = mid+1;
int pos = first;
while( i <= mid || j <= last ){
if( i > mid ){
while( j <= last ) merge[pos++] = arr[j++];
break;
}

if( j > last ){
while( i <= mid ) merge[pos++] = arr[i++];
break;
}
//等于小的
merge[pos++] = arr[i] >= arr[j] ? arr[j++] : arr[i++];
}

for (pos = first; pos <= last; pos++){
arr[pos] = merge[pos];
System.out.print(arr[pos]+" ");
}
System.out.println();
}


每趟排序之后:

start : 3 9 7 6 8 4 5 10 2 1
first:0,last:1,mid:0 : 3 9
process: 3 9 7 6 8 4 5 10 2 1
first:0,last:2,mid:1 : 3 7 9
process: 3 7 9 6 8 4 5 10 2 1
first:3,last:4,mid:3 : 6 8
process: 3 7 9 6 8 4 5 10 2 1
first:0,last:4,mid:2 : 3 6 7 8 9
process: 3 6 7 8 9 4 5 10 2 1
first:5,last:6,mid:5 : 4 5
process: 3 6 7 8 9 4 5 10 2 1
first:5,last:7,mid:6 : 4 5 10
process: 3 6 7 8 9 4 5 10 2 1
first:8,last:9,mid:8 : 1 2
process: 3 6 7 8 9 4 5 10 1 2
first:5,last:9,mid:7 : 1 2 4 5 10
process: 3 6 7 8 9 1 2 4 5 10
first:0,last:9,mid:4 : 1 2 3 4 5 6 7 8 9 10
process: 1 2 3 4 5 6 7 8 9 10
end  : 1 2 3 4 5 6 7 8 9 10


基数排序

/*
* 基数排序(桶排序)
*/
public static void basketSort(int arr[])//arr为待排序数组
{
int len=arr.length;
int bask[][]=new int[10][len];
int index[]=new int[10];
int max=Integer.MIN_VALUE;
System.out.println(max);
//找到数组中长度最大的数的长度 max
for(int i=0;i<len;i++){
max=max>(Integer.toString(arr[i]).length())?max:(Integer.toString(arr[i]).length());
}
String str;
//先将长度相同的元素放在一起,并且按照长度进行排序
//然后将长度相同的元素排序。
for(int i=max-1;i>=0;i--){
for(int j=0;j<len;j++){
str="";
//如果数组有的元素的长度小于最大长度,补0
if(Integer.toString(arr[j]).length()<max){
for(int k=0;k<max-Integer.toString(arr[j]).length();k++)
str+="0";
}
str+=Integer.toString(arr[j]);
bask[str.charAt(i)-'0'][index[str.charAt(i)-'0']++]=arr[j];
}
int pos=0;
for(int j=0;j<10;j++)
{
for(int k=0;k<index[j];k++)
{
arr[pos++]=bask[j][k];
}
}
for(int x=0;x<10;x++)
index[x]=0;
}
}


每趟排序之后:

start : 3 9 7 6 8 4 5 10 2 1
process: 10 1 2 3 4 5 6 7 8 9
process: 1 2 3 4 5 6 7 8 9 10
end  : 1 2 3 4 5 6 7 8 9 10
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息