说一说排序和查找

今天说一说数据结构中的排序和查找

我最早遇见也是用过最多的排序就是选择排序。

一、选择排序是一种非常基本的排序算法。其基本思想就是将线性表看成有序和无序两个部分,有序子表是a[0:i-1],无序子表是a[i:n-1]。排序过程中每次从无序子表中选出最小的一个元素,将其添加到有序子表的末尾,有序子表保持有序且长度加1,无序子表长度减1,重复这个过程知道无序子表为空。

    不多说,直接看代码:

public void selectSort(int[] a){
    if (a==null)
        return;
    if (a.length==0)
        return;
    //外循环只需循环n-1    for (int i=0;i<a.length-1;i++){
        for (int j = i+1;j<a.length;j++){
            if (a[i]>a[j]){
                //交换函数
                swap(a,i,j);
            }
        }
    }
}

因为每循环一次,就有一个数已经有序,所以外循环只需执行n-1次即可。

二、插入排序:同样,也是将线性表看成有序和无序两个部分,有序子表是a[0:i-1],无序子表是a[i:n-1],排序过程中是每次从无序子表中取出一个元素,将其插入到有序子表的正确位置,使有序子表保持有序并逐渐增大,知道所有记录都插入有序表。

    看代码:

public void insertSort(int[] a){
    if (a==null)
        return;
    if (a.length==0)
        return;
    for (int i=1;i<a.length;i++){
        int x =a[i];
        int j;
        for (j=i-1;j>=0 && a[j]>x;j--)
            a[j+1] = a[j];
        a[j+1] = x;
    }
}

    内循环就是为了给无序子表中的元素找到正确的位置,不破坏有序子表的有序性。

三、冒泡排序:与之前的选择排序相比,选择排序一趟下来能找到最小的那个元素,而冒泡排序每趟能找到的是最大的那个元素。冒泡排序将两两相邻的元素进行比较,碰到逆序则交换,直到循环完成。

    看代码:

public void bubbleSort(int[] a){
    if (a==null)
        return;
    if (a.length==0)
        return;
    int flag = 1;
    for (int i=0;i<a.length && flag!=0;i++){
        //这里减i是为了提高效率
        flag = 0;
        for (int j = 0;j<a.length-i-1;j++){
            if (a[j]>a[j+1]){
                swap(a,j,j+1);
                flag = 1;
            }
        }
    }
}

    因为每次排序都会有一个元素有序,为了提高效率,避免重复扫描元素,内循环将每次排序后的有序个数减掉。

四、快速排序:又称为分区交换排序,是目前已知的实测平均速度最快的一种排序方法,它是对冒泡排序的一种改进。

    看代码吧

public void quickSort(int[] a){
    if (a==null)
        return;
    if (a.length==0)
        return;
    quickSort(a,0,a.length-1);
}

public void quickSort(int[] a,int low,int high){
    if (low>high)
        return;
    int k = divide(a,low,high);
    quickSort(a,low,k-1);
    quickSort(a,k+1,high);
}

private int divide(int[] a, int low, int high) {
    int x = a[low];
    while (low<high){
        while (low<high && a[high]>=x)
            high--;
        a[low] = a[high];
        while (low<high && a[low]<x)
            low++;
        a[high] = a[low];
    }
    a[low] = x;
    return low;
}

    先从后面遍历,如果比第一个值小,则停止,再从前面开始遍历,如果比第一个值大,则停止,知道数组有序。

五、归并排序:归并排序是将两个有序的序列的有序合并。因此将两个有序子序列合并成一个有序序列是归并排序的基础算法。

    看代码。。。

public void quickSort(int[] a){
    if (a==null)
        return;
    if (a.length==0)
        return;
    quickSort(a,0,a.length-1);
}

public void quickSort(int[] a,int low,int high){
    if (low>high)
        return;
    int k = divide(a,low,high);
    quickSort(a,low,k-1);
    quickSort(a,k+1,high);
}

private int divide(int[] a, int low, int high) {
    int x = a[low];
    while (low<high){
        while (low<high && a[high]>=x)
            high--;
        a[low] = a[high];
        while (low<high && a[low]<x)
            low++;
        a[high] = a[low];
    }
    a[low] = x;
    return low;
}

    归并排序很稳定,而且效率也很高。

六、堆排序:堆排序是在直接选择排序的基础上借助于堆而形成的一种排序方法。

    看代码...

public void heapSort(int[] a){
    if (a==null)
        return;
    if (a.length==0)
        return;
    int len = a.length;
    buildHeap(a,len);
    while (len>1){
        swap(a,0,len-1);
        len--;
        adjustHeap(a,0,len);
    }
}

private void adjustHeap(int[] a, int i, int len) {
    int maxIndex = i;
    if (2*i < len && a[2*i]>a[maxIndex])
        maxIndex = 2*i;
    if (2*i+1 < len && a[2*i+1]>a[maxIndex])
        maxIndex = 2*i+1;
    if (maxIndex != i){
        swap(a,i,maxIndex);
        adjustHeap(a,maxIndex,len);
    }
}

private void buildHeap(int[] a, int len) {
    for (int i = (len-1)/2;i>=0;i--)
        adjustHeap(a,i,len);
}

    其实堆排序只要了解原理就很容易写出来,反正我不喜欢它。

七、计数排序:基数排序就是找出线性表中的最小值和最大值,然后将之间出现的元素放到一个数组中计数,当计数完成,再遍历一遍不就是已经排好序的数据了吗

    再说一遍,看代码。。。

public void countSort(int[] a){
    if (a==null)
        return;
    if (a.length==0)
        return;
    int max = a[0],min = a[0];
    for (int i=0;i<a.length;i++){
        if (a[i]<min)
            min = a[i];
        if (a[i]>max)
            max = a[i];
    }

    int[] t = new int[max-min+1];
    int abs = 0-min;
    for (int i=0;i<a.length;i++){
        t[a[i]+abs]++;
    }

    int i = 0,index = 0;
    while (index<a.length){
        if (t[i]!=0){
            a[index++] = i-abs;
            t[i]--;
        }else {
            i++;
        }
    }
}

    计数排序很长适用于稳定在某一区间的数据,在这种情况下,时间复杂对和空间复杂度都很惊人

八、二分查找:博主目前能拿出手的就是二分查找了

    不说了,心酸,看代码吧

public int binSearch(int[] a,int x){
    if (a==null)
        return -1;
    if (a.length==0)
        return -1;
    int left = 0;
    int right = a.length-1;
    int mid = (left+right)/2;
    while (a[mid]!=x){
        if (a[mid]<x){
            left = mid+1;
        }else {
            right = mid-1;
        }

        if (left>right)
            return -1;
        mid = (left+right)/2;
    }
    return mid;
}
    注意,二分查找的前提数组事先是有序的才行。




猜你喜欢

转载自blog.csdn.net/yanghan1222/article/details/80185267