排序算法代码整理

来源:互联网 发布:灰色系统预测软件 编辑:程序博客网 时间:2024/05/23 00:06

注:以下均为升序排序;

简单排序:

冒泡排序:相邻的元素两两比较,将最大的数放在右边。

int n;long[] theArray = new long[n];public void bubbleSort(){    for (int out = n-1 ; out > 1 ; out--){        for (int in = 0 ; in < out ; in++){            if (theArray[in] > theArray[in+1]){                swap(in,in+1);            }        }    }}public void swap(int x,int y){    long temp = theArray[x];    theArray[x] = theArray[y];    theArray[y] = temp;}


选择排序:选定第一个元素暂且认为是最小的,依次与剩下的元素比较有比其小的则交换,再交换到第一个位置;然后再定义第二个为次最小的重复上述步骤;

public void selectSort(){    for (int out = 0 ; out < n-1 ; out ++){        int min = out ;        for (int in = out + 1 ; in < n ; in++){            if (theArray[in] < theArray[min]){                min = in;            }            swap(min,out);        }    }}


        选择排序和冒泡排序的比较次数是一样的都是n的平方次,但是选择排序的交换次数要比冒泡排序的交换次数少。选择排序最大的交换次数为n-1,冒泡排序交换的最大次数为(n-1)!次,所以在n很大的时候选择选择排序,在n很小的时候,如果比较的时间级比交换的时间级小也可以选择选择排序。


插入排序:插入排序适合待排序数组中有一部分已经是有序的数组,找到没有序的边界后,将其依次的向前(后)交换到左边大(小)右边小(大)的位置,复制的次数太多了,才能找到暂时的正确位置。

public void insertSort(){    for (int out = 1 ; out < n ; out++){        long temp = theArray[out];        int in = out;        while(in >0 && theArray[in-1] > temp){            theArray[in] = theArray[in-1];            --in;        }        theArray[in] = temp;    }}


归并排序:现将待排序的数组从中间划分成两部分,然后递归将原数组一直到划分为每个数组只有一个元素或两个元素,再依次将划分好的数组两两有序的合并到一个数组,直到全部有序的合并。

public void mergeSort(){    long[] workSpace = new long[n];    recMergeSort(workSpace,0,n-1);}public void recMergeSort(long[] workSpace,int lowerBound,int upperBound){    int mid = (lowerBound + upperBound)/2;    recMergeSort(workSpace,lowerBound,mid);//递归    recMergeSort(workSpace,mid+1,upperBound);    merge(workSpace,lowerBound,mid+1,upperBound);//合并}public void merge(long[] workSpace,int lowerPtr,int highPtr,int upperBound){    int lowerBound = lowerPtr;    int mid = highPtr - 1;    int n = lowerBound + upperBound -1;    int j =0;    while(lowerPtr <= mid && highPtr <= upperBound){        if (theArray[lowerPtr] < theArray[highPtr]){            workSpace[j++] = theArray[lowerPtr++];        }        else {            workSpace[j++] = theArray[highPtr++];        }    }    while(lowerPtr <= mid){        workSpace[j++] = theArray[lowerPtr++];//中后半部分比中前半部分短    }    while (highPtr <= upperBound){        workSpace[j++] = theArray[highPtr++];//中前半部分比中后半部分短    }    for (int i = 0 ; i < n ; i++){        theArray[lowerBound+i] = workSpace[i];    }}

高级排序

希尔排序:原理与插入排序一致,不同点就是增加一个间隔序列h=h*3+1(1,4,13,40,121,364...)。

public void shellSort(){    int h = 1;    while(h <= n/3){        h = h*3 +1;    }    while(h > 0){        for (int out = h ;out < n ; out++){            long temp = theArray[out];            int in = out;            while(in > h-1 && theArray[in-h] > temp){                theArray[in] = theArray[in-h];                in-=h;            }            theArray[in] = temp;        }        h = (h-1)/3;    }}


快速排序:将待排序的数组,划分成一边是比选出来的比较值小(大)一边是比比较值小(大),依次采用递归的方式最后为有序的数组。

public void quickSort(){    recQuickSort(0,n-1);}public void recQuickSort(int left,int right){    int size = left + right - 1;    if (size <= 3){        manualSort(left,right);//选用“三个数据项取中”的方式选出一个比较值,是了避免选中的比较值太小或太大;    }    else{        long media = medianOf3(left,right);        int partition = partitionIt(left,right,media);        recQuickSort(left,partition);        recQuickSort(partition+1,right);    }}public int partitionIt(int left,int right,long media){    int leftPtr = left -1;    int rightPtr = right;    while(true){        while (theArray[++leftPtr] < media);        while (theArray[--rightPtr] > media);        if (leftPtr >= rightPtr){            break;        }else{        swap(leftPtr,rightPtr);        }    }    swap(leftPtr,right);    return leftPtr;}public long medianOf3(int left,int right){    int mid = (left+right)/2;    if (theArray[left] > theArray[mid]){        swap(left,mid);    }    if (theArray[mid] > theArray[right]){        swap(mid,right);    }    if (theArray[left] > theArray[right]){        swap(left,right);    }    swap(mid,right);    return theArray[right];}public void manualSort(int left, int right){    int size = left + right - 1;    if (size <= 1){        return;    }    if (size ==2){        if (theArray[left] > theArray[right]){            swap(left, right);        }        return;    }    else{        if (theArray[left] > theArray[right - 1]) {            swap(left, right -1);        }        if (theArray[left] > theArray[right]){            swap(left, right);        }        if (theArray[right - 1] > theArray[right]) {            swap(right-1,right);        }    }}

堆排序:

根据初始数组构造大顶堆(大顶堆:每个节点的关键字大于等于子节点的关键字,升序采用大顶推;小顶堆:每个节点的关键字小于等于子节点的关键字,降序采用小顶推);

每次交换大顶堆的第一个和最后一个元素,推出最后一个元素,然后把剩下的元素重新调整为大顶堆。

public void HeapAdjust(int[] array, int parent, int length) {    int temp = array[parent]; // temp保存当前父节点    int child = 2 * parent + 1; // 先获得左孩子    while (child < length) {        if (child + 1 < length && array[child] < array[child + 1]) {            child++;// 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点        }        if (temp >= array[child])// 如果父结点的值已经大于孩子结点的值,则直接结束            break;        array[parent] = array[child];// 把孩子结点的值赋给父结点        parent = child;// 选取孩子结点的左孩子结点,继续向下筛选        child = 2 * child + 1;    }    array[parent] = temp;}public void heapSort(int[] list) {    for (int i = list.length / 2; i >= 0; i--) {// 循环建立初始堆        HeapAdjust(list, i, list.length - 1);    }    for (int i = list.length - 1; i > 0; i--) {        int temp = list[i]; // 最后一个元素和第一元素进行交换        list[i] = list[0];        list[0] = temp;        HeapAdjust(list, 0, i);// 筛选 R[0] 结点,得到i-1个结点的堆    }}


各种排序的时间复杂度与空间复杂度: