常用排序算法的Java实现

[b]八大内部排序:[/b]
[img]https://img-my.csdn.net/uploads/201207/17/1342514529_5795.jpg[/img]
1.直接插入排序:时间复杂度O(n2),空间复杂度O(1),稳定的排序算法
/**
* 直接插入排序
* <ul>
* <li>从第一个元素开始,该元素可以认为已经被排序</li>
* <li>取出下一个元素,在已经排序的元素序列中从后向前扫描</li>
* <li>如果该元素(已排序)大于新元素,将该元素移到下一位置</li>
* <li>重复步骤3,直到找到已排序的元素小于或者等于新元素的位置</li>
* <li>步将新元素插入到该位置中</li>
* <li>重复步骤2</li>
* </ul>
* @param : arr
*/
public static void insertSort(int[] arr){
if(arr==null||arr.length<=1)
return;
int len = arr.length, temp, j;
for(int i=1;i<len;i++){
temp = arr[i];
for(j=i;j>0&&temp<arr[j-1];j--)
arr[j] = arr[j-1];
arr[j] = temp;
}
}


2.希尔排序:时间复杂度O(nlogn),空间复杂度O(1),不稳定的排序算法
/**
* 希尔排序
* @param arr
*/
public static void shellSort(int arr[]) {
if(arr==null||arr.length<=1)
return;
int i, j, gap;
int n = arr.length;
for (gap=n/2; gap>0; gap= gap/2) {
for (i = 0; i<gap; i++) { // 直接插入排序
for (j=i+gap; j<n; j=j+gap){
if (arr[j] < arr[j-gap]) {
int temp = arr[j];
int k = j-gap;
while (k>=0 && arr[k]>temp) {
arr[k+gap] = arr[k];
k = k-gap;
}
arr[k+gap] = temp;
}
}
}
}
}


3.选择排序:时间复杂度O(n2),空间复杂度O(1),不稳定的排序算法
/**  
* 选择排序
* <li>在未排序序列中找到最小元素,存放到排序序列的起始位置</li>
* <li>再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾。</li>
* <li>以此类推,直到所有元素均排序完毕。</li>
* @param numbers
*/
public static void selectSort(int[] arr){
if(arr==null||arr.length<=1)
return;
int minIndex = 0;
int temp = 0;
for(int i=0; i<arr.length-1;i++){
minIndex = i;
for(int j=i+1;j<arr.length;j++){
if(arr[j]<arr[minIndex])
minIndex = j;
}
if(minIndex!=i){
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}


4.堆排序:时间复杂度O(nlogn),空间复杂度O(1),不稳定的排序算法

/**
* 堆排序
* @param arr
*/
public static void heapSort(int[] arr) {
if (arr == null || arr.length <= 1)
return;
buildMaxHeap(arr);
for (int i = arr.length - 1; i >= 1; i--) {
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
maxHeap(arr, i, 0);
}
}

private static void buildMaxHeap(int[] arr) {
if (arr == null || arr.length <= 1) {
return;
}
int half = arr.length / 2;
for (int i = half; i >= 0; i--) {
maxHeap(arr, arr.length, i);
}
}

private static void maxHeap(int[] arr, int heapSize, int index) {
int left = index * 2 + 1;
int right = index * 2 + 2;

int largest = index;
if (left < heapSize && arr[left] > arr[index]) {
largest = left;
}

if (right < heapSize && arr[right] > arr[largest]) {
largest = right;
}

if (index != largest) {
int temp = arr[index];
arr[index] = arr[largest];
arr[largest] = temp;
maxHeap(arr, heapSize, largest);
}
}



5.冒泡排序:时间复杂度O(n2),空间复杂度O(1),稳定的排序算法
/**
* 冒泡排序
* <ul>
* <li>比较相邻的元素。如果第一个比第二个大,就交换他们两个。</li>
* <li>对每一对相邻元素做同样工作,从开始第一对到最后一对。最后的元素会是最大数。</li>
* <li>针对所有的元素重复以上的步骤,除了最后一个。</li>
* <li>持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。</li>
* </ul>
* @param : arr
*/
public static void bubbleSort(int[] arr){
if(arr==null||arr.length<=1)
return;
int len = arr.length, temp;
for(int i=1;i<len;i++){
for(int j=0;j<len-i;j++){
if(arr[j]>arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}


6.快速排序:时间复杂度O(nlogn),空间复杂度O(nlogn),不稳定的排序算法
 
public static void quickSort(int[] arr) {
if(arr==null||arr.length<=1)
return;
subQuickSort(arr, 0, arr.length - 1);
}

/**
* 快速排序
* <ul>
* <li>从数列中挑出一个元素,称为“基准”</li>
* <li>重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割之后,
* 该基准是它的最后位置。这个称为分割(partition)操作。</li>
* <li>递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。</li>
* </ul>
* @param arr
* @param start
* @param end
*/
private static void subQuickSort(int[] arr, int start, int end){
if(arr==null||arr.length<=1)
return;
int s = start;
int e = end;
int value = arr[start];
while(s<e){
while(s<e && arr[e]>=value)
e--;
if(s<e){
int temp = arr[s];
arr[s] = arr[e];
arr[e] = temp;
}

while(s<e && arr[s]<=value)
s++;
if(s<e){
int temp = arr[s];
arr[s] = arr[e];
arr[e] = temp;
}
}

if(s>start)
subQuickSort(arr, start, s-1);
if(e<end)
subQuickSort(arr, e+1, end);
}


7.归并排序:时间复杂度O(log2n),空间复杂度O(n),稳定的排序算法

public static void mergeSort(int[] arr) {
if(arr==null||arr.length<=1)
return;
sortArray(arr, 0, arr.length - 1);
}

private static void sortArray(int[] arr, int start, int end) {
// 单个元素不需要排序,直接返回
if (start == end) {
return;
}

int sortSize = end - start + 1;
int seperate;
if (sortSize % 2 == 0) {
seperate = start + sortSize / 2 - 1;
} else {
seperate = start + sortSize / 2;
}

sortArray(arr, start, seperate);
sortArray(arr, seperate + 1, end);

mergeArray(arr, start, seperate, end);
}

private static void mergeArray(int[] arr, int start, int seperate, int end) {
int totalSize = end - start + 1;
int size1 = seperate - start + 1;
int size2 = end - seperate;

int[] array1 = new int[size1];
int[] array2 = new int[size2];

for (int i = 0; i < size1; i++) {
array1[i] = arr[start + i];
}

for (int i = 0; i < size2; i++) {
array2[i] = arr[seperate + 1 + i];
}

int mergeCount = 0;
int index1 = 0;
int index2 = 0;

while (mergeCount < totalSize) {
// 先检查有没有其中的一个数组已经处理完
if (index1 == size1) {
for (int i = index2; i < size2; i++) {
arr[start + mergeCount] = array2[i];
mergeCount++;
index2++;
}
} else if (index2 == size2) {
for (int i = index1; i < size1; i++) {
arr[start + mergeCount] = array1[i];
mergeCount++;
index1++;
}
} else {
int value1 = array1[index1];
int value2 = array2[index2];

if (value1 == value2) {
arr[start + mergeCount] = value1;
arr[start + mergeCount + 1] = value1;
mergeCount += 2;
index1++;
index2++;
} else if (value1 < value2) {
arr[start + mergeCount] = value1;
mergeCount++;
index1++;
} else if (value1 > value2) {
arr[start + mergeCount] = value2;
mergeCount++;
index2++;
}
}
}
}


8.基数排序:时间复杂度O(d(n+r)),空间复杂度O(n+r),稳定的排序算法
r为基数,d为位数。则基数排序的时间复杂度为O(d(n+r))

/**
* 基数排序
* @param arr: 待排列的数组
* @param digit:排列数值中最大值位数
*
*/
public static void radixSort(int[] arr, int digit) {
if(arr==null||arr.length<=1)
return;
final int radix = 10; // 基数
int i = 0, j = 0;
int begin = 0;
int end = arr.length-1;
int[] count = new int[radix]; // 存放各个桶的数据统计个数
int[] bucket = new int[end - begin + 1];

// 按照从低位到高位的顺序执行排序过程
for (int d = 1; d <= digit; d++) {
// 置空各个桶的数据统计
for (i = 0; i < radix; i++) {
count[i] = 0;
}
// 统计各个桶将要装入的数据个数
for (i = begin; i <= end; i++) {
j = getDigit(arr[i], d);
count[j]++;
}
// count[i]表示第i个桶的右边界索引
for (i = 1; i < radix; i++) {
count[i] = count[i] + count[i - 1];
}
// 将数据依次装入桶中
// 这里要从右向左扫描,保证排序稳定性
for (i = end; i >= begin; i--) {
j = getDigit(arr[i], d); // 求出关键码的第k位的数字, 例如:576的第3位是5
bucket[count[j] - 1] = arr[i]; // 放入对应的桶中,count[j]-1是第j个桶的右边界索引
count[j]--; // 对应桶的装入数据索引减一
}
// 将已分配好的桶中数据再倒出来,此时已是对应当前位数有序的表
for (i = begin, j = 0; i <= end; i++, j++) {
arr[i] = bucket[j];
}
}
}
// 获取x这个数的d位数上的数字
// 比如获取123的1位数,结果返回3
private static int getDigit(int x, int d) {
return ((x / (int)Math.pow(10, d)) % 10);
}


[b]八大排序算法比较:[/b]
[img]http://blog.chinaunix.net/attachment/201201/18/21457204_1326898064RUxx.jpg[/img]
[color=red]注:直接选择是算法本身是稳定的,只是用顺序存储结构来表现时,会产生不稳定的情况,若用链表来实现,则是稳定的。[/color]


八大排序算法合集:


public class Sort {

/**
* 直接插入排序
* <ul>
* <li>从第一个元素开始,该元素可以认为已经被排序</li>
* <li>取出下一个元素,在已经排序的元素序列中从后向前扫描</li>
* <li>如果该元素(已排序)大于新元素,将该元素移到下一位置</li>
* <li>重复步骤3,直到找到已排序的元素小于或者等于新元素的位置</li>
* <li>步将新元素插入到该位置中</li>
* <li>重复步骤2</li>
* </ul>
* @param : arr
*/
public static void insertSort(int[] arr){
if(arr==null||arr.length<=1)
return;
int len = arr.length, temp, j;
for(int i=1;i<len;i++){
temp = arr[i];
for(j=i;j>0&&temp<arr[j-1];j--)
arr[j] = arr[j-1];
arr[j] = temp;
}
}

/**
* 希尔排序
* @param arr
*/
public static void shellSort(int arr[]) {
if(arr==null||arr.length<=1)
return;
int i, j, gap;
int n = arr.length;
for (gap=n/2; gap>0; gap= gap/2) {
for (i = 0; i<gap; i++) { // 直接插入排序
for (j=i+gap; j<n; j=j+gap){
if (arr[j] < arr[j-gap]) {
int temp = arr[j];
int k = j-gap;
while (k>=0 && arr[k]>temp) {
arr[k+gap] = arr[k];
k = k-gap;
}
arr[k+gap] = temp;
}
}
}
}
}

/**
* 选择排序
* <li>在未排序序列中找到最小元素,存放到排序序列的起始位置</li>
* <li>再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾。</li>
* <li>以此类推,直到所有元素均排序完毕。</li>
* @param numbers
*/
public static void selectSort(int[] arr){
if(arr==null||arr.length<=1)
return;
int minIndex = 0;
int temp = 0;
for(int i=0; i<arr.length-1;i++){
minIndex = i;
for(int j=i+1;j<arr.length;j++){
if(arr[j]<arr[minIndex])
minIndex = j;
}
if(minIndex!=i){
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}

/**
* 堆排序
* @param arr
*/
public static void heapSort(int[] arr) {
if (arr == null || arr.length <= 1) {
return;
}
buildMaxHeap(arr);
for (int i = arr.length - 1; i >= 1; i--) {
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
maxHeap(arr, i, 0);
}
}

private static void buildMaxHeap(int[] arr) {
if (arr == null || arr.length <= 1) {
return;
}
int half = arr.length / 2;
for (int i = half; i >= 0; i--) {
maxHeap(arr, arr.length, i);
}
}

private static void maxHeap(int[] arr, int heapSize, int index) {
int left = index * 2 + 1;
int right = index * 2 + 2;

int largest = index;
if (left < heapSize && arr[left] > arr[index]) {
largest = left;
}

if (right < heapSize && arr[right] > arr[largest]) {
largest = right;
}

if (index != largest) {
int temp = arr[index];
arr[index] = arr[largest];
arr[largest] = temp;
maxHeap(arr, heapSize, largest);
}
}

/**
* 冒泡排序
* <ul>
* <li>比较相邻的元素。如果第一个比第二个大,就交换他们两个。</li>
* <li>对每一对相邻元素做同样工作,从开始第一对到最后一对。最后的元素会是最大数。</li>
* <li>针对所有的元素重复以上的步骤,除了最后一个。</li>
* <li>持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。</li>
* </ul>
* @param : arr
*/
public static void bubbleSort(int[] arr){
if(arr==null||arr.length<=1)
return;
int len = arr.length, temp;
for(int i=1;i<len;i++){
for(int j=0;j<len-i;j++){
if(arr[j]>arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}


public static void quickSort(int[] arr) {
if(arr==null||arr.length<=1)
return;
subQuickSort(arr, 0, arr.length - 1);
}

/**
* 快速排序
* <ul>
* <li>从数列中挑出一个元素,称为“基准”</li>
* <li>重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割之后,
* 该基准是它的最后位置。这个称为分割(partition)操作。</li>
* <li>递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。</li>
* </ul>
* @param arr
* @param start
* @param end
*/
private static void subQuickSort(int[] arr, int start, int end){
if(arr==null||arr.length<=1)
return;
int s = start;
int e = end;
int value = arr[start];
while(s<e){
while(s<e && arr[e]>=value)
e--;
if(s<e){
int temp = arr[s];
arr[s] = arr[e];
arr[e] = temp;
}

while(s<e && arr[s]<=value)
s++;
if(s<e){
int temp = arr[s];
arr[s] = arr[e];
arr[e] = temp;
}
}

if(s>start)
subQuickSort(arr, start, s-1);
if(e<end)
subQuickSort(arr, e+1, end);
}

public static void mergeSort(int[] arr) {
if(arr==null||arr.length<=1)
return;
sortArray(arr, 0, arr.length - 1);
}

private static void sortArray(int[] arr, int start, int end) {
// 单个元素不需要排序,直接返回
if (start == end) {
return;
}

int sortSize = end - start + 1;
int seperate;
if (sortSize % 2 == 0) {
seperate = start + sortSize / 2 - 1;
} else {
seperate = start + sortSize / 2;
}

sortArray(arr, start, seperate);
sortArray(arr, seperate + 1, end);

mergeArray(arr, start, seperate, end);
}

private static void mergeArray(int[] arr, int start, int seperate, int end) {
int totalSize = end - start + 1;
int size1 = seperate - start + 1;
int size2 = end - seperate;

int[] array1 = new int[size1];
int[] array2 = new int[size2];

for (int i = 0; i < size1; i++) {
array1[i] = arr[start + i];
}

for (int i = 0; i < size2; i++) {
array2[i] = arr[seperate + 1 + i];
}

int mergeCount = 0;
int index1 = 0;
int index2 = 0;

while (mergeCount < totalSize) {
// 先检查有没有其中的一个数组已经处理完
if (index1 == size1) {
for (int i = index2; i < size2; i++) {
arr[start + mergeCount] = array2[i];
mergeCount++;
index2++;
}
} else if (index2 == size2) {
for (int i = index1; i < size1; i++) {
arr[start + mergeCount] = array1[i];
mergeCount++;
index1++;
}
} else {
int value1 = array1[index1];
int value2 = array2[index2];

if (value1 == value2) {
arr[start + mergeCount] = value1;
arr[start + mergeCount + 1] = value1;
mergeCount += 2;
index1++;
index2++;
} else if (value1 < value2) {
arr[start + mergeCount] = value1;
mergeCount++;
index1++;
} else if (value1 > value2) {
arr[start + mergeCount] = value2;
mergeCount++;
index2++;
}
}
}
}

/**
* 基数排序
* @param arr: 待排列的数组
* @param digit:排列数值中最大值位数
*
*/
public static void radixSort(int[] arr, int digit) {
if(arr==null||arr.length<=1)
return;
final int radix = 10; // 基数
int i = 0, j = 0;
int begin = 0;
int end = arr.length-1;
int[] count = new int[radix]; // 存放各个桶的数据统计个数
int[] bucket = new int[end - begin + 1];

// 按照从低位到高位的顺序执行排序过程
for (int d = 1; d <= digit; d++) {
// 置空各个桶的数据统计
for (i = 0; i < radix; i++) {
count[i] = 0;
}
// 统计各个桶将要装入的数据个数
for (i = begin; i <= end; i++) {
j = getDigit(arr[i], d);
count[j]++;
}
// count[i]表示第i个桶的右边界索引
for (i = 1; i < radix; i++) {
count[i] = count[i] + count[i - 1];
}
// 将数据依次装入桶中
// 这里要从右向左扫描,保证排序稳定性
for (i = end; i >= begin; i--) {
j = getDigit(arr[i], d); // 求出关键码的第k位的数字, 例如:576的第3位是5
bucket[count[j] - 1] = arr[i]; // 放入对应的桶中,count[j]-1是第j个桶的右边界索引
count[j]--; // 对应桶的装入数据索引减一
}
// 将已分配好的桶中数据再倒出来,此时已是对应当前位数有序的表
for (i = begin, j = 0; i <= end; i++, j++) {
arr[i] = bucket[j];
}
}
}
// 获取x这个数的d位数上的数字
// 比如获取123的1位数,结果返回3
private static int getDigit(int x, int d) {
return ((x / (int)Math.pow(10, d)) % 10);
}


// 打印完整序列
public static void printArr(int[] arr) {
for (int value : arr) {
System.out.print(value + "\t");
}
System.out.println();
}

public static void main(String[] args) {
int[] arr = { 50, 123, 543, 187, 49, 30, 0, 2, 11, 100,2000,3002,1001};

System.out.print("排序前:\t");
printArr(arr);
insertSort(arr);
shellSort(arr);
selectSort(arr);
heapSort(arr);
bubbleSort(arr);
quickSort(arr);
mergeSort(arr);
radixSort(arr,4);
System.out.print("排序后:\t");
printArr(arr);
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值