一、冒泡法排序
冒泡排序思想:两两比较相邻的关键字,如果顺序相反则交换,知道没有反序的记录为止。
- 每遍历一次,将一个最小的元素冒到顶。数据从a[0]开始存储。
public static void BubbleSort1(int[] arr) {
int i, j;
for (i = 0; i < arr.length - 1; i++) {
//
for (j = arr.length - 2; j >= i; j--) {
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1);
}
}
}
}
- 冒泡法优化:如果前依次排序已经是有序的,则后序无需排序。直接可以出结果。
public static void BubbleSort2(int[] a) {
int i, j;
boolean flag = true;
for (i = 0; i < a.length - 1 && flag; i++) {
flag = false;// 初始为false。
for (j = a.length - 2; j >= i; j--) {
if (a[j] > a[j + 1]) {
swap(a, j, j + 1);
flag = true;// 如果数据交换 flag变为true
}
}
}
}
public static void swap(int[] a, int i, int j) {
int tmp;
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
二、插入排序
-记录数据比较少、基本有序的话,效率高。
插入排序思想:在要排序的数组中,假设前面n-1个数,已经排好序,现在要把第n的数插到前面的有序数列中去。此插入排序 从a[0]开始存储数据
public static void InsertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
for (int j = i; j<arr.length; j--) {
int tmp = arr[i];
arr[j] = arr[j - 1];
arr[j] = tmp;
}
}
}
三、希尔排序
希尔排序思想:将一组数据按某个增量分成若干组(每组记录的小标相差d),每组进行插入排序。
public static void ShellSort(int[] a) {
int i, j;
int increment = a.length;
do {
increment = increment / 3 + 1; // 增量序列
for (i = increment + 1; i < a.length; i++) {
if (a[i] < a[i - increment]) {
// 将a[i]插入有序增量子表
a[0] = a[i];// 暂存a[0]
for (j = i - increment; j > 0 && a[0] < a[j]; j -= increment) {
a[j + increment] = a[j];// 记录后移 查找插入位置
}
a[j + increment] = a[0];// 插入
}
}
} while (increment > 1);
}
四、堆排序
注意:堆是完全二叉树,结点比左子树都大,比右子树都小。
堆排序思想:先将序列组成完全二叉树,然后利用大顶堆,将待排序的序列构造成一个大顶堆,此时这个序列的最大值即为根节点。将根节点移走(就是讲根节点与堆数组的为元素交换,此时*尾元素变成最大值。),将剩下的n-1个元素重新构建成一个堆,这样就会得到n *个元素的次大值,如此反复就可以得到有序序列。堆排序,需要O(1)辅助空间。
public static void HeapSort(int[] a) {
//将数组构建成大顶堆,a.length-0的结点 都有孩子。
for (int i = a.length / 2; i > 0; i--) {
//i为小树的根节点。
HeapAdjust(a, i, a.length - 1);
}
for (int i = a.length - 1; i > 1; i--) {
//将堆顶记录和当前为排序的子序列的最后一个记录交换
swap(a, 1, i);
//将arr[1….i_1]重新调整成大顶堆
HeapAdjust(a, 1, i - 1);
}
}
/**调整堆结构 :a 堆排序数组 ; i 要调整的节点;n 尾节点*/
private static void HeapAdjust(int[] a, int i, int n) {
int child;
int temp = a[i];
for (; 2 * i <= n; i = child) {
// for循环进行调整左右节点与父亲节点互换。并使i指向最后一个堆数组。并把i元素移到最后边。
// 相当于调整第i个元素。(将其位置变成空穴,将堆数组的a[i]放到合适的空穴中。)
child = 2 * i;
if (child < n && a[child] < a[child + 1])
++child;
if (temp <= a[child])
a[i] = a[child];
else {
break;
}
}
a[i] = temp;
}
五、归并排序:
归并排序思想 :将两个或两个以上有序合并成一个新的有序序列。即把待排序的序列跟个城若干个子序列,每个子序列都是有序的。
/**
* @param left 数组开始下标
* @param right 数组末尾下标
*/
public static void mergeSort(int[] arr, int[] tempArray, int left, int right) {
if (left < right) {
int middle = (left + right) / 2;
mergeSort(arr, tempArray, left, middle);
mergeSort(arr, tempArray, middle + 1, right);
Merge(arr, tempArray, left, middle + 1, right);
}
}
/**
* @param letf 第一段的开始
* @param middle 第二段的开始
* @param righ 第二段的结束
*/
private static void Merge(int[] arr, int[] tempArray, int left,
int middle,int right) {
int leftEnd = middle - 1;
int tempIndex = left;
int tempLength = right - left + 1;
while ((left <= leftEnd) && (middle <= right)) {
if (arr[left] <= arr[middle])
tempArray[tempIndex++] = arr[left++];
else
tempArray[tempIndex++] = arr[middle++];
}
while (left <= leftEnd)
tempArray[tempIndex++] = arr[left++];
while (middle <= right)
tempArray[tempIndex++] = arr[middle++];
for (int i = 0; i < tempLength; i++) {
arr[right] = tempArray[right];
right--;
}
}
六、快速排序
快速排序:通过一趟排序将待排序记录分割成独立的两半部分,其中一部分记录的关键字均比领一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的
public static void quickSort(int[] arr,int low,int high){
if(low<high){
//找出中枢关键字,并且把数组分成[low,mid-1],[mid+1,high].
int mid=getmiddle(arr,low,high);
quickSort(arr,low,mid-1);
quickSort(arr,mid+1,high);
}
}
public static int getmiddle(int[] arr,int low,int high){
//选取arr[low]为中枢关键最
int pivotkey=arr[low];
while(low<high){
while(low<high&&arr[high]>=pivotkey){
high--;
}
//将比中枢关键字小的交换到低端。
swap(arr,low,high);
while(low<high&&arr[low]<=pivotkey){
low++;
}
//将比枢轴关键字大的交换到高端。
swap(arr,low,high);
}
return low;
}