线性表排序

//冒泡排序
public void bubbleSort(int[] list) {
    int temp = 0; // 用来交换的临时数

    // 要遍历的次数
    for (int i = 0; i < list.length - 1; i++) {
        // 从后向前依次的比较相邻两个数的大小,遍历一次后,把数组中第i小的数放在第i个位置上
        for (int j = list.length - 1; j > i; j--) {
            // 比较相邻的元素,如果前面的数大于后面的数,则交换
            if (list[j - 1] > list[j]) {
                temp = list[j - 1];
                list[j - 1] = list[j];
                list[j] = temp;
            }
        }

        System.out.format("第 %d 趟:\t", i);
        printAll(list);
    }
}

// 冒泡排序优化
public void bubbleSort_2(int[] list) {
    int temp = 0; // 用来交换的临时数
    boolean bChange = false; // 交换标志

    // 要遍历的次数
    for (int i = 0; i < list.length - 1; i++) {
        bChange = false;
        // 从后向前依次的比较相邻两个数的大小,遍历一次后,把数组中第i小的数放在第i个位置上
        for (int j = list.length - 1; j > i; j--) {
            // 比较相邻的元素,如果前面的数大于后面的数,则交换
            if (list[j - 1] > list[j]) {
                temp = list[j - 1];
                list[j - 1] = list[j];
                list[j] = temp;
                bChange = true;
            }
        }

        // 如果标志为false,说明本轮遍历没有交换,已经是有序数列,可以结束排序
        if (false == bChange)
            break;

        System.out.format("第 %d 趟:\t", i);
        printAll(list);
    }
}

//快速排序
private void quickSort(int[] list, int left, int right) {
    // 左下标一定小于右下标,否则就越界了
    if (left < right) {
        // 对数组进行分割,取出下次分割的基准标号
        int base = division(list, left, right);

        System.out.format("base = %d:\t", list[base]);
        printPart(list, left, right);

        // 对“基准标号“左侧的一组数值进行递归的切割,以至于将这些数值完整的排序
        quickSort(list, left, base - 1);

        // 对“基准标号“右侧的一组数值进行递归的切割,以至于将这些数值完整的排序
        quickSort(list, base + 1, right);
    }
}

public int division(int[] list, int left, int right) {
    // 以最左边的数(left)为基准
    int base = list[left];
    while (left < right) {
        // 从序列右端开始,向左遍历,直到找到小于base的数
        while (left < right && list[right] >= base)
            right--;
        // 找到了比base小的元素,将这个元素放到最左边的位置
        list[left] = list[right];

        // 从序列左端开始,向右遍历,直到找到大于base的数
        while (left < right && list[left] <= base)
            left++;
        // 找到了比base大的元素,将这个元素放到最右边的位置
        list[right] = list[left];
    }

    // 最后将base放到left位置。此时,left位置的左侧数值应该都比left小;
    // 而left位置的右侧数值应该都比left大。
    list[left] = base;
    return left;
}

//插入排序
public void insertSort(int[] list) {
   // 打印第一个元素
   System.out.format("i = %d:\t", 0);
   printPart(list, 0, 0);

   // 第1个数肯定是有序的,从第2个数开始遍历,依次插入有序序列
   for (int i = 1; i < list.length; i++) {
       int j = 0;
       int temp = list[i]; // 取出第i个数,和前i-1个数比较后,插入合适位置

       // 因为前i-1个数都是从小到大的有序序列,所以只要当前比较的数(list[j])比temp大,就把这个数后移一位
       for (j = i - 1; j >= 0 && temp < list[j]; j--) {
           list[j + 1] = list[j];
       }
       list[j + 1] = temp;

       System.out.format("i = %d:\t", i);
       printPart(list, 0, i);
   }
}

//希尔排序
public void shellSort(int[] list) {
   int gap = list.length / 2;

   while (1 <= gap) {
       // 把距离为 gap 的元素编为一个组,扫描所有组
       for (int i = gap; i < list.length; i++) {
           int j = 0;
           int temp = list[i];

           // 对距离为 gap 的元素组进行排序
           for (j = i - gap; j >= 0 && temp < list[j]; j = j - gap) {
               list[j + gap] = list[j];
           }
           list[j + gap] = temp;
       }

       System.out.format("gap = %d:\t", gap);
       printAll(list);
       gap = gap / 2; // 减小增量
   }
}

//选择排序

//堆排序
public void HeapAdjust(int[] array2, int parent, int length) {
    int temp = array2[parent]; // temp保存当前父节点
    int child = 2 * parent + 1; // 先获得左孩子

    while (child < length) {
        // 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
        if (child + 1 < length && array2[child] < array2[child + 1]) {
            child++;
        }

        // 如果父结点的值已经大于孩子结点的值,则直接结束
        if (temp >= array2[child])
            break;

        // 把孩子结点的值赋给父结点
        array2[parent] = array2[child];

        // 选取孩子结点的左孩子结点,继续向下筛选
        parent = child;
        child = 2 * child + 1;
    }

    array2[parent] = temp;
}

public void heapSort(int[] list) {
    // 循环建立初始堆
    for (int i = list.length / 2; i >= 0; i--) {
        HeapAdjust(list, i, list.length);
    }

    // 进行n-1次循环,完成排序
    for (int i = list.length - 1; i > 0; i--) {
        // 最后一个元素和第一元素进行交换
        int temp = list[i];
        list[i] = list[0];
        list[0] = temp;

        // 筛选 R[0] 结点,得到i-1个结点的堆
        HeapAdjust(list, 0, i);
        System.out.format("第 %d 趟: \t", list.length - i);
        printPart(list, 0, list.length - 1);
    }
}

//归并排序
public void Merge(int[] array2, int low, int mid, int high) {
    int i = low; // i是第一段序列的下标
    int j = mid + 1; // j是第二段序列的下标
    int k = 0; // k是临时存放合并序列的下标
    int[] array2 = new int[high - low + 1]; // array2是临时合并序列

    // 扫描第一段和第二段序列,直到有一个扫描结束
    while (i <= mid && j <= high) {
        // 判断第一段和第二段取出的数哪个更小,将其存入合并序列,并继续向下扫描
        if (array2[i] <= array2[j]) {
            array2[k] = array2[i];
            i++;
            k++;
        } else {
            array2[k] = array2[j];
            j++;
            k++;
        }
    }

    // 若第一段序列还没扫描完,将其全部复制到合并序列
    while (i <= mid) {
        array2[k] = array2[i];
        i++;
        k++;
    }

    // 若第二段序列还没扫描完,将其全部复制到合并序列
    while (j <= high) {
        array2[k] = array2[j];
        j++;
        k++;
    }

    // 将合并序列复制到原始序列中
    for (k = 0, i = low; i <= high; i++, k++) {
        array2[i] = array2[k];
    }
}

Last updated