排序效率分析2

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nc.norman.sorter;

/**
 *折半插入排序
 * @author NC
 * @version 1.0
 */
public class BInsertSorter extends Sorter {

    @Override
    public void sort(SortArray array, boolean order) {
        int n = array.length;
        int i, j, low, high, m;
        for (i = 2; i <= n; i++) {
            array.setKey(i); //保存关键字
            low = 1;//设定比较区间
            high = i - 1;
            while (low <= high) {
                m = (low + high) / 2;
                if (array.compareToKey(m, !order)) {
                    high = m - 1;//插入点在低半区
                } else {
                    low = m + 1;//插入点在后半区
                }
            }
            //找到插入点,开始移动,插入
            for (j = i - 1; j >= high + 1; j--) {
                array.setElement(j + 1, array.getElement(j));
                array.addMoveCount();
            }
            array.addInsertCount();
            array.setElement(high + 1, array.getKey()); //插入正确的位置
        }
    }
}

 

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nc.norman.sorter;

/**
 * 冒泡排序
 * 方法:相邻两元素进行比较,如有需要则进行交换,每完成一次循环就将最大元素排在最后(如从小到大排序),下一次循环是将其他的数进行类似操作。
 * 性能:比较次数O(n^2),n^2/2;交换次数O(n^2),n^2/4
 * @author NC
 * @version 1.0
 */
public class BubbleSorter extends Sorter {

    @Override
    public void sort(SortArray array, boolean order) {
        int n = array.length;
        int i, j, flag = 1;
        for (i = n; i > 1 && flag == 1; i--) {//该趟最后一个数为关键字,假定为最大的;要求当一趟冒泡过程中不再有数据交换,则排序结束
            flag = 0;
            for (j = 1; j <= i - 1; j++) {
                if (array.compare(j, j + 1, !order)) { //关键字前面的数相邻(注意是相邻)两两比较,大的就往后冒
                    array.swap(j, j + 1);
                    flag = 1;
                }
            }
        }
    }
}
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nc.norman.sorter;

/**
 *桶排序的思想就是把区间[0,1)划分成n个相同大小的子区间,或称桶,然后将n个输入数分布到各个桶中去。
 * 因为输入数均匀分布在[0,1)上,所以一般不会有很多数落在 一个桶中的情况。为得到结果,先对各个桶中的数进行排序,然后按次序把各桶中的元素列 出来即可。
 * @author NC
 */
public class BucketSorter extends Sorter {

    //这个方法只设正序的
    @Override
    public void sort(SortArray array, boolean order) {
                sort(array.getArray(),0,array.length,array.length*2);
                //SortArray的随机数据是1到两倍数组长度之间
    }

    public void sort(int[] array, int from, int len, int max) {
        int[] temp = new int[len];
        int[] count = new int[max];
        //分配到各个桶里面
        for (int i = 0; i < len; i++) {
            count[array[from + i]]++;
        }
        //对每个桶排序
        for (int i = 1; i < max; i++) {
            count[i] = count[i] + count[i - 1];
        }
        //按顺序把每个桶中的元素列出来
        System.arraycopy(array, from, temp, 0, len);
        for (int k = len - 1; k >= 0; k--) {
            array[--count[temp[k]]] = temp[k];
        }
    }
}
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nc.norman.sorter;

/**
 * 计数排序
 * @author NC
 * @version 
 */
public class CountSorter extends Sorter {

    @Override
    public void sort(SortArray array, boolean order) {
        int n = array.length;
        int[] ds = new int[n]; //分配临时空间
        int i, j, count = 0;
        for (j = 1; j <= n; j++) {
            count = 0;
            for (i = 1; i <= n; i++) {
                if (i != j)//关键字与其他数比较
                {
                    if (array.compare(i, j, order)) {
                        count++;
                    } else if (array.equal(i, j) && j < i) {
                        //j<i保证排序的稳定性,去掉时当数据有一样大时会出错
                        count++;
                    }
                }
            }
            ds[count] = array.getElement(j);
        }
        array.setArray(ds);
    }
}
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nc.norman.sorter;

/**
 * 堆排序
 * @author NC
 * @version 1.0
 */
public class HeapSorter extends Sorter {

    private static int heapAdjust(SortArray array, int start, int end, boolean order) {
        int flag = 0;
        int left = 0;
        int right = 0;
        int max = 0;
        left = start * 2;
        right = start * 2 + 1;
        while (left <= end) {
            max = left;
            if (right <= end) {
                if (array.compare(left, right, order)) {
                    max = right;
                } else {
                    max = left;
                }
            }
            if (array.compare(start, max, order)) {
                array.swap(start, max);
                flag = 1;
                start = max;
            } else {
                break;
            }
            left = start * 2;
            right = start * 2 + 1;
        }
        return flag;
    }

    private static void buildHeap(SortArray array, boolean order) {
        int n = array.length;
        int i;
        for (i = n / 2; i > 0; i--) {
            heapAdjust(array, i, n, order);
        }
    }

    @Override
    public void sort(SortArray array, boolean order) {
        int n = array.length;
        int i;
        buildHeap(array, order);
        for (i = n; i > 1; i--) {
            array.swap(1, i);
            heapAdjust(array, 1, i - 1, order);
        }
    }
}

 

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nc.norman.sorter;

/**
 * 插入排序
 * 方法:将一个记录插入到已排好序的有序表(有可能是空表)中,从而得到一个新的记录数增1的有序表。
 * 性能:比较次数O(n^2),n^2/4
 * 复制次数O(n),n^2/4
 * 比较次数是前两者的一般,而复制所需的CPU时间较交换少,所以性能上比冒泡排序提高一倍多,而比选择排序也要快。
 * @author NC
 * @version 1.0
 */
public class InsertSorter extends Sorter {

    @Override
    public void sort(SortArray array, boolean order) {
        int n = array.length;
        int i, j;
        for (i = 2; i <= n; i++) {
            if (array.compare(i, i - 1, order)) {//比关键字大的话
                array.setKey(i); //暂存关键字
                array.setElement(i, array.getElement(i - 1)); //比关键字大,后移(前面已经比较过了)
                array.addMoveCount();
                for (j = i - 1; j >= 1 && array.compareToKey(j, !order); j--) {//比关键字大,后移;比关键字小的话,就退出,找到要插入的位置了
                    array.setElement(j + 1, array.getElement(j));
                    array.addMoveCount();
                }
                array.setElement(j + 1, array.getKey()); //插入正确的位置
                array.addInsertCount();
            }
        }

    }
}
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nc.norman.sorter;

/**
 * 归并排序
 * @author NC
 * @version 1.0
 */
public class MergeSorter extends Sorter {

    //非递归归并排序
    @Override
    public void sort(SortArray array, boolean order) {
        int n = array.length;
        int beforeLen = 1; //合并前序列的长度
        int afterLen = 1;//合并后序列的长度
        for (beforeLen = 1; afterLen <= n; beforeLen = afterLen) {
            afterLen = beforeLen << 1; //合并后序列的长度是合并前的两倍
            int i = 1;//开始合并时第一个序列的起始位置下标,每次都是从1开始
            while (i + afterLen - 1 <= n) {//足够分成两个子表
                Merge(array, i, i + beforeLen - 1, i + afterLen - 1, order);
                i += afterLen;
            }
            if (i + beforeLen <= n) {
                Merge(array, i, i + beforeLen - 1, n, order);
            }
        }
    }

    //递归归并排序
    public void mergeSort2(SortArray array, boolean order) {
        mergeSort(array, 1, array.length, order);
    }

    //递归归并排序
    public void mergeSort2(SortArray array) {
        mergeSort(array, 1, array.length, Sorter.POSITIVE);
    }

    private void mergeSort(SortArray array, int left, int right, boolean order) {

        if (left < right) {
            int center = (left + right) / 2;
            mergeSort(array, left, center, order);
            mergeSort(array, center + 1, right, order);
            Merge(array, left, center, right, order);
        }
    }

    private void Merge(SortArray array, int left, int center, int right, boolean order) {
        //[1,2,3,4] left=1,ceter=2,right=4
        int[] temp = new int[right - left + 1];//存放被合并后的元素
        int i = left;
        int j = center + 1;
        int k = 0;
        while (i <= center && j <= right) {
            array.addInsertCount();
            if (array.compare(i, j, order)) {
                temp[k++] = array.getElement(i++);
            } else {
                temp[k++] = array.getElement(j++);
            }
        }
        while (i <= center) {
            array.addInsertCount();
            temp[k++] = array.getElement(i++);
        }
        while (j <= right) {
            array.addInsertCount();
            temp[k++] = array.getElement(j++);
        }
        //把t[]的元素复制回a[]
        for (i = left, k = 0; i <= right; i++, k++) {
            array.setElement(i, temp[k]);
        }
    }
}

 

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nc.norman.sorter;

/**
 * 奇偶交换排序
 * @author NC
 * @version
 */
public class ParitySorter extends Sorter {

    @Override
    public void sort(SortArray array, boolean order) {
        int n = array.length;
        int i = 0, j = 0, tag = 1;
        for (j = 0; j < n; j++) {
            for (i = j % 2 + 1; i <= n - 1; i += 2) {
                //每次仅对奇数或偶数下标处理,步长为2
                if (array.compare(i, i + 1, !order)) {
                    array.swap(i, i + 1);
                    tag = 0;//记录比较趟数
                }
            }
            tag++;
            if (tag == 3) {
                break;
            }
            /*如果待排序列本身已经有序,
            则只需执行再次内层循环即对奇偶下标元素分别扫描一次
            就可判断出序列已经有序*/
        }
    }
}
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nc.norman.sorter;

/**
 * 快速排序
 * 快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。
 * 步骤为:
 * 1. 从数列中挑出一个元素,称为 "基准"(pivot),
 * 2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
 *    在这个分割之后,该基准是它的最后位置。这个称为分割(partition)操作。
 * 3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
 * 递回的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。
 *    虽然一直递回下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
 * @author NC
 * @version 1.0
 */
public class QuickSorter extends Sorter {

    private int partition(SortArray array, int low, int high, boolean order) {
        int key = array.getElement(low); //用子表的第一个记录作为枢轴记录
        while (low < high) {//从表的两端交替地向中间扫描
            while (low < high && array.compareNotMoreThan(array.getElement(high), key, !order)) {
                high--;
            }
            array.setElement(low, array.getElement(high));
            while (low < high && array.compareNotMoreThan(array.getElement(low), key, order)) {
                low++;
            }
            array.setElement(high, array.getElement(low));
            array.addExchangeCount();
        }
        array.setElement(low, key);
        array.addInsertCount();
        return low;
    }

    private void qSort(SortArray array, int low, int high, boolean order) {
        int pivotloc;
        if (low < high) {//保证长度大于1,递归的出口
            pivotloc = partition(array, low, high, order); //将表low-high一分为2,用枢轴位置来分
            qSort(array, low, pivotloc - 1, order); //对低子表递归排序
            qSort(array, pivotloc + 1, high, order); //对高子表递归排序
        }
    }

    @Override
    public void sort(SortArray array, boolean order) {
        int n = array.length;
        qSort(array, 1, n, order);
    }
}

 

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nc.norman.sorter;

/**
 * 选择排序
 * 方法:每一趟从待排序的数据元素中选出最小(或最大)的一个元素, 顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。
 * 性能:比较次数O(n^2),n^2/2
 * 交换次数O(n),n
 * 交换次数比冒泡排序少多了,由于交换所需CPU时间比比较所需的CUP时间多,所以选择排序比冒泡排序快。
 * 但是N比较大时,比较所需的CPU时间占主要地位,所以这时的性能和冒泡排序差不太多,但毫无疑问肯定要快些。
 * @author NC
 * @version 1.0
 */
public class SelectSorter extends Sorter {

    @Override
    public void sort(SortArray array, boolean order) {
        int n = array.length;
        int x, k, i, j;
        for (i = 1; i < n; i++) {
            k = i; //暂时定为最小的关键字
            for (j = i + 1; j <= n; ++j) {
                if (array.compare(j, k, order)) {
                    k = j; //与i之后的n-i个数依次比较,记录小值下标
                }
            }
            if (k != i) {//k值改变,原先定的不是最小。找到最小的,交换
                array.swap(i, k);
            }
        }
    }
}
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nc.norman.sorter;

/**
 * 希尔排序
 * @author NC
 * @author 1.0
 */
public class ShellInsertSorter extends Sorter {

    @Override
    public void sort(SortArray array, boolean order) {
        int n = array.length;
        int k = n / 2;
        while (k > 0) {
            shellInsert(array, k, order);
            k = k / 2; //分配增量
        }
    }

    private void shellInsert(SortArray array, int dk, boolean order) {
        int n = array.length;
//dk为增量
        int i, j;
        for (i = dk + 1; i <= n; i++) {
//共n-(dk+1)+1个子序列,分别进行直接插入排序
            if (array.compare(i, i - dk, order)) {//比关键字大的话
                array.setKey(i); //暂存关键字
                for (j = i - dk; j > 0 && array.compareToKey(j, !order); j = j - dk) {//比关键字小的就退出,找到位置了。j<=0说明方序列已经是有序的
                    array.setElement(j + dk, array.getElement(j)); //记录后移,找到插入位置时退出
                    array.addMoveCount();
                }
                array.setElement(j + dk, array.getKey()); //插入关键字
                    array.addInsertCount();
            }
        }
    }
}

源码请见上一篇的附件 

你可能感兴趣的:(算法,J#)