七种排序算法
排序方法一般有:
冒泡排序 选择排序 插入排序 快排(快速排序) 希尔排序 归并排序 堆排序
冒泡,插入,归并是稳定的
选择,快排,希尔,堆,不稳定
简单排序推荐冒泡,复杂排序推荐快排
稳定性
假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的
冒泡排序:
通过嵌套循环,遍历数列所有元素,一次比较两个,判断是否交换大小,最大值沉底或最小值浮顶之后开启下一轮遍历,直至排序完成。
for(int i= 0;i<c.length-1;i++){
for(int j=0;j<c.length-1-i;j++){
if(c[j]>c[j+1]){
int temp = c[j+1];
c[j+1] = c[j];
c[j] = temp;
}
}
}
选择排序
在未排序的列中找到最大(小)值,放到最前端或者最后端,再从剩余未排序的列中找到最大(小)值。
只需要交换下标,内部循环完之后,交换最小值和 i值
for(int i= 0;i <c.length-1;i++) {
int min = i;
for(int j=i+1;j<c.length;j++){
if(c[min]>c[j] ) {
min = j;
}
}
if(i !=min){
int temp = c[i];
c[i]= c[min];
c[min]=temp;
}
}
插入排序
将已排序的当做有序序列,下一个未排序的从后往前遍历,插入前面有序序列的合适位置 。temp=i=j,然后j-i位与temp比较。
for(int i=0;i<c.length;i++)
{
int temp = c[i]; //把第i给位置的值给temp (拿出来的操作)
int j;
for( j= i;j>0&&c[j-1]>temp;j--) //只能j>0写前面,不然判断会越界
{
c[j]=c[j-1];
}
c[j]= temp;
}
快排(快速排序)
快排是冒泡的升级版,最好的内排序(在内存中进行的排序过程)
先走左边,左边走通了,再走右边

static void QuickSort(int[] arr,int min,int max ){
if(min>=max){
return;
}
int left = min;
int right = max;
int key = arr[min];
while(left<right){
while(left<right && arr[right]>=key ){
right--;
}
arr[left] = arr[right]; //找到小的值,占了key的位置
while(left<right && arr[left]<=key){
left++;
}
arr[right]=arr[left]; //找到大的值,占了上一个循环找的小于key值得位置
arr[left] = key; //key的值,占了上一个循环找到的大的字
//这两个while 就实现了一次查找, 小 key 大 的排序
}
//外圈while 继续查找, 直到右边没有比key大的,左边没有比key小的。 即(left = right)
QuickSort(arr,min,left-1); //左迭代,排序key左边的。
QuickSort(arr,right+1,max); //右迭代,排序key右边的。
希尔排序
gap分组:按arr.length /2 分为多组,再组内使用插入排序,
private static void shellSort(int[] arr) {
//step:步长
for (int step = arr.length / 2; step > 0; step /= 2) {
//对一个步长区间进行比较 [step,arr.length)
for (int i = step; i < arr.length; i++) {
int value = arr[i];
int j;
//对步长区间中具体的元素进行比较
for (j = i - step; j >= 0 && arr[j] > value; j -= step) {
//j为左区间的取值,j+step为右区间与左区间的对应值。
arr[j + step] = arr[j];
}
//此时step为一个负数,[j + step]为左区间上的初始交换值
arr[j + step] = value;
}
}
}
归并排序
这个好复杂,还需要与数组等长的辅助空间,
public class Main {
public static void main(String[] args) {
int[] arr = {11, 44, 23, 67, 88, 65, 34, 48, 9, 12};
int[] tmp = new int[arr.length]; //新建一个临时数组存放
mergeSort(arr, 0, arr.length - 1, tmp);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
public static void merge(int[] arr, int low, int mid, int high, int[] tmp) {
int i = 0;
int j = low, k = mid + 1; //左边序列和右边序列起始索引
while (j <= mid && k <= high) {
if (arr[j] <= arr[k]) {
tmp[i++] = arr[j++];
} else {
tmp[i++] = arr[k++];
}
}
//若左边序列还有剩余,则将其全部拷贝进tmp[]中
while (j <= mid) {
tmp[i++] = arr[j++];
}
while (k <= high) {
tmp[i++] = arr[k++];
}
for (int t = 0; t < i; t++) {
arr[low + t] = tmp[t];
}
}
public static void mergeSort(int[] arr, int low, int high, int[] tmp) {
if (low < high) {
int mid = (low + high) / 2;
mergeSort(arr, low, mid, tmp); //对左边序列进行归并排序
mergeSort(arr, mid + 1, high, tmp); //对右边序列进行归并排序
merge(arr, low, mid, high, tmp); //合并两个有序序列
}
}
}
堆排序
靠二叉树来实现的,构建大堆顶,将堆顶与堆尾元素交换,
private static void heapSort(int[] arr) {
//创建堆
for (int i = (arr.length - 1) / 2; i >= 0; i--) {
//从第一个非叶子结点从下至上,从右至左调整结构
adjustHeap(arr, i, arr.length);
}
//调整堆结构+交换堆顶元素与末尾元素
for (int i = arr.length - 1; i > 0; i--) {
//将堆顶元素与末尾元素进行交换
int temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
//重新对堆进行调整
adjustHeap(arr, 0, i);
}
}
/**
* 调整堆
* @param arr 待排序列
* @param parent 父节点
* @param length 待排序列尾元素索引
*/
private static void adjustHeap(int[] arr, int parent, int length) {
//将temp作为父节点
int temp = arr[parent];
//左孩子
int lChild = 2 * parent + 1;
while (lChild < length) {
//右孩子
int rChild = lChild + 1;
// 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
if (rChild < length && arr[lChild] < arr[rChild]) {
lChild++;
}
// 如果父结点的值已经大于孩子结点的值,则直接结束
if (temp >= arr[lChild]) {
break;
}
// 把孩子结点的值赋给父结点
arr[parent] = arr[lChild];
//选取孩子结点的左孩子结点,继续向下筛选
parent = lChild;
lChild = 2 * lChild + 1;
}
arr[parent] = temp;
}
}


浙公网安备 33010602011771号