算法之排序

1、冒泡排序:

package com.arithmetic.sorts;
//定义一个名为BubbleSort的类,其中包含了一个名为bubbleSort的静态方法用于实现冒泡排序算法。
//然后,在main方法中创建一个整型数组,并调用bubbleSort方法对数组进行排序。
//使用printArray方法打印排序后的数组。
//冒泡排序算法的主要思想是重复地比较相邻的元素,如果它们的顺序不符合要求(例如,前一个元素大于后一个元素),则交换它们。
//通过这种方式,较大的元素会逐渐“冒泡”到数组的末尾。该算法的时间复杂度为O(n^2),其中n是数组的长度。
public class BubbleSortDemo {
    public static void main(String[] args) {
    	
        int[] array = {64, 34, 25, 12, 22, 11, 90};

        System.out.println("排序前数组:");
        printArray(array);

        bubbleSort(array);

        System.out.println("排序后数组:");
        printArray(array);
    }

    public static void bubbleSort(int[] array) {
        int n = array.length;

        // 重复 n-1 次
        for (int i = 0; i < n - 1; i++) {

            // 每次遍历比较相邻的元素
            for (int j = 0; j < n - i - 1; j++) {

                // 如果当前元素大于下一个元素,则交换它们
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
    }

    public static void printArray(int[] array) {
        for (int element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }
}

2、 插入排序:

package com.arithmetic.sorts;
//定义一个名为InsertionSort的类,其中包含一个名为insertionSort的静态方法用于实现插入排序算法。
//在main方法中创建一个整型数组,并调用insertionSort方法对数组进行排序。
//使用printArray方法打印排序后的数组。
//插入排序算法的主要思想是将一个元素插入到已排序序列的正确位置中。
//从数组的第二个元素开始,逐个将当前元素与已排序的元素进行比较,找到正确的插入位置,并将元素插入。
//通过这种方式,数组逐渐构建出一个有序序列。该算法的时间复杂度为O(n^2),其中n是数组长度。
public class InsertionSortDemo {
    public static void main(String[] args) {
        int[] array = {64, 34, 25, 12, 22, 11, 90};

        System.out.println("排序前数组:");
        printArray(array);

        insertionSort(array);

        System.out.println("排序后数组:");
        printArray(array);
    }

    public static void insertionSort(int[] array) {
        int n = array.length;

        for (int i = 1; i < n; i++) {
            int key = array[i];
            int j = i - 1;

            // 将比关键字大的元素向后移动一位
            while (j >= 0 && array[j] > key) {
                array[j + 1] = array[j];
                j--;
            }

            array[j + 1] = key;
        }
    }

    public static void printArray(int[] array) {
        for (int element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }
}

 3、选择排序:

package com.arithmetic.sorts;
//定义一个名为SelectionSort的类,其中包含了一个名为selectionSort的静态方法用于实现选择排序算法。
//然后,在main方法中创建一个整型数组,并调用selectionSort方法对数组进行排序。
//最后,使用printArray方法打印排序后的数组。
//选择排序的主要思想是从未排序的部分中选择最小的元素,并将其与未排序部分的第一个元素交换位置。
//重复这个步骤,直到整个数组都有序。该算法的时间复杂度为O(n^2),其中n是数组长度。
public class SelectionSortDemo {
	
    public static void main(String[] args) {
    	
        int[] array = {64, 25, 12, 22, 11};

        System.out.println("排序前数组:");
        printArray(array);

        selectionSort(array);

        System.out.println("排序后数组:");
        printArray(array);
    }

    public static void selectionSort(int[] array) {
        int n = array.length;

        for (int i = 0; i < n-1; i++) {
            int minIndex = i;

            // 在未排序的部分中找到最小的元素
            for (int j = i+1; j < n; j++) {
                if (array[j] < array[minIndex]) {
                    minIndex = j;
                }
            }

            // 将最小的元素与当前位置交换
            int temp = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp;
        }
    }

    public static void printArray(int[] array) {
        for (int element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }
}

4、快速排序:

package com.arithmetic.sorts;
import java.util.Arrays;
//quickSort方法是递归调用的快速排序方法,partition方法用于将数组分成两个部分并返回分割点的索引。
//swap方法用于交换数组中指定索引位置的元素。
//在main方法中,创建一个测试数组并对其进行排序,然后输出排序后的结果。
public class QuickSortDemo {
    
    public static void main(String[] args) {
        int[] arr = {5, 2, 9, 1, 3, 6, 4, 8, 7};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
    
    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int pivotIndex = partition(arr, low, high);
            quickSort(arr, low, pivotIndex - 1);
            quickSort(arr, pivotIndex + 1, high);
        }
    }
    
    public static int partition(int[] arr, int low, int high) {
        int pivot = arr[high];
        int i = low - 1;
        
        for (int j = low; j < high; j++) {
            if (arr[j] < pivot) {
                i++;
                swap(arr, i, j);
            }
        }
        
        swap(arr, i + 1, high);
        return i + 1;
    }
    
    public static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

 5、归并排序:

package com.arithmetic.sorts;
import java.util.Arrays;
//mergeSort方法是递归调用的归并排序方法。
//它将数组划分成左右两个子数组,然后分别对这两个子数组进行排序,并最后将排好序的子数组合并。
//merge方法用于将两个已排序的子数组合并成一个有序的数组。
//在main方法中,创建一个测试数组并对其进行排序,然后输出排序后的结果。
public class MergeSortDemo {
    
    public static void main(String[] args) {
        int[] arr = {5, 2, 9, 1, 3, 6, 4, 8, 7};
        mergeSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
    
    public static void mergeSort(int[] arr, int low, int high) {
        if (low < high) {
            int mid = (low + high) / 2;
            mergeSort(arr, low, mid);
            mergeSort(arr, mid + 1, high);
            merge(arr, low, mid, high);
        }
    }
    
    public static void merge(int[] arr, int low, int mid, int high) {
        int leftLength = mid - low + 1;
        int rightLength = high - mid;
        int[] leftArr = new int[leftLength];
        int[] rightArr = new int[rightLength];
        
        for (int i = 0; i < leftLength; i++) {
            leftArr[i] = arr[low + i];
        }
        
        for (int j = 0; j < rightLength; j++) {
            rightArr[j] = arr[mid + 1 + j];
        }
        
        int i = 0, j = 0, k = low;
        while (i < leftLength && j < rightLength) {
            if (leftArr[i] <= rightArr[j]) {
                arr[k] = leftArr[i];
                i++;
            } else {
                arr[k] = rightArr[j];
                j++;
            }
            k++;
        }
        
        while (i < leftLength) {
            arr[k] = leftArr[i];
            i++;
            k++;
        }
        
        while (j < rightLength) {
            arr[k] = rightArr[j];
            j++;
            k++;
        }
    }
}

6、堆排序:

package com.arithmetic.sorts;
import java.util.Arrays;
//heapSort方法用于执行堆排序。
//它首先通过循环从数组的一半开始,依次构建最大堆。
//然后,它从数组末尾开始逐步将最大元素放到堆的末尾,并用heapify方法重新调整堆。
//heapify方法用于将某个节点及其子树调整为最大堆的形式。
//在main方法中,创建一个测试数组并对其进行排序,然后输出排序后的结果。
//堆排序的时间复杂度是O(nlogn),其中n是数组的长度。
//堆排序是一种不稳定的排序算法,因为在对堆进行调整时,会交换元素的位置,可能导致相等元素的顺序发生改变。
public class HeapSortDemo {
    
    public static void main(String[] args) {
        int[] arr = {5, 2, 9, 1, 3, 6, 4, 8, 7};
        heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    
    public static void heapSort(int[] arr) {
        int n = arr.length;
        
        // 构建最大堆
        for (int i = n/2 - 1; i >= 0; i--) {
            heapify(arr, n, i);
        }
        
        // 逐步将最大元素放到堆末尾,然后重新调整堆
        for (int i = n - 1; i >= 0; i--) {
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;
            
            heapify(arr, i, 0);
        }
    }
    
    public static void heapify(int[] arr, int n, int i) {
        int largest = i; // 最大元素的索引
        int left = 2 * i + 1; // 左子节点的索引
        int right = 2 * i + 2; // 右子节点的索引
        
        // 如果左子节点大于最大元素,则更新最大元素的索引
        if (left < n && arr[left] > arr[largest]) {
            largest = left;
        }
        
        // 如果右子节点大于最大元素,则更新最大元素的索引
        if (right < n && arr[right] > arr[largest]) {
            largest = right;
        }
        
        // 如果最大元素不是当前节点,则交换当前节点和最大元素,并递归调整交换后的子树
        if (largest != i) {
            int temp = arr[i];
            arr[i] = arr[largest];
            arr[largest] = temp;
            
            heapify(arr, n, largest);
        }
    }
}

7、最大堆:

package com.datastructure.heap;
//堆是完全二叉树:除最后一层外,其他层的节点都是满的,最后一层的节点尽可能地连续靠左排列。
//堆中每个节点的值都大于等于(或小于等于)其子节点的值。根节点的值是最大(或最小)的。

//堆有两种常见的类型:最大堆和最小堆。

//最大堆:堆中每个节点的值都大于等于其子节点的值。根节点的值是最大的。
//最小堆:堆中每个节点的值都小于等于其子节点的值。根节点的值是最小的。
//堆主要用于高效地查找和删除最大(最小)元素,而插入元素则比较慢。
//在代码实现中,通常使用数组来表示堆。堆的根节点存储在数组的第一个元素位置,其他节点依次填充数组。节点i的左子节点索引为2 * i,右子节点索引为2 * i + 1,父节点索引为i / 2。

//常见的堆操作有:
//插入新元素:将新元素放在堆的最后一个位置上,并进行向上或向下的堆化操作,以保持堆的性质。
//删除根节点:将根节点和最后一个节点交换位置,删除最后一个节点,并进行向下的堆化操作,以保持堆的性质。
//堆的应用包括:
//堆排序:利用堆的性质,可以进行高效的排序。
//优先队列:堆可以用于实现优先队列,其中每个元素都有一个关联的优先级。
//Top k 问题:通过使用最小堆或最大堆来实现一个动态的Top k集合,可以高效地找出最大或最小的k个元素。
//图算法中的最短路径问题:使用堆来选择下一个要拓展的节点,以达到减少计算量的目的。

//创建一个最大堆对象,初始化一个可以容纳10个元素的堆。
//实现插入元素、移除最大元素、维护堆性质等方法。
//在main方法中,向堆中插入了一些元素,并打印堆的内容。
//最后,移除了最大元素并打印出来。
//这个例子中,数组heap的0索引是不使用的,实际数据存放从1索引开始。
//parent、leftChild和rightChild等方法用于计算给定位置的父节点和子节点在数组中的索引。
这个实现的时间复杂度是O(log n),其中n是堆的大小。
public class MaxHeap {

    private int[] heap;
    private int size;
    private int maxSize;

    private static final int FRONT = 1;

    public MaxHeap(int maxSize) {
        this.maxSize = maxSize;
        this.size = 0;
        this.heap = new int[maxSize + 1];
        this.heap[0] = Integer.MAX_VALUE;
    }

    private int parent(int pos) {
        return pos / 2;
    }

    private int leftChild(int pos) {
        return 2 * pos;
    }

    private int rightChild(int pos) {
        return 2 * pos + 1;
    }

    private boolean isLeaf(int pos) {
        return pos >= size / 2 && pos <= size;
    }

    private void swap(int pos1, int pos2) {
        int temp = heap[pos1];
        heap[pos1] = heap[pos2];
        heap[pos2] = temp;
    }

    private void maxHeapify(int pos) {
        if (!isLeaf(pos)) {
            if (heap[pos] < heap[leftChild(pos)] || heap[pos] < heap[rightChild(pos)]) {
                if (heap[leftChild(pos)] > heap[rightChild(pos)]) {
                    swap(pos, leftChild(pos));
                    maxHeapify(leftChild(pos));
                } else {
                    swap(pos, rightChild(pos));
                    maxHeapify(rightChild(pos));
                }
            }
        }
    }

    public void insert(int element) {
        if (size >= maxSize) {
            System.out.println("Heap is full");
            return;
        }

        heap[++size] = element;
        int current = size;

        while (heap[current] > heap[parent(current)]) {
            swap(current, parent(current));
            current = parent(current);
        }
    }

    public int removeMax() {
        if (size == 0) {
            return -1;
        }

        int max = heap[FRONT];
        heap[FRONT] = heap[size--];
        maxHeapify(FRONT);

        return max;
    }

    public void printHeap() {
        for (int i = 1; i <= size / 2; i++) {
            System.out.print("Parent: " + heap[i] + ", Left Child: " +
                    heap[leftChild(i)] + ", Right Child: " + heap[rightChild(i)]);
            System.out.println();
        }
    }

    public static void main(String[] args) {
        MaxHeap maxHeap = new MaxHeap(10);
        maxHeap.insert(5);
        maxHeap.insert(3);
        maxHeap.insert(17);
        maxHeap.insert(10);
        maxHeap.insert(84);
        maxHeap.insert(19);
        maxHeap.insert(6);
        maxHeap.insert(22);
        maxHeap.insert(9);

        maxHeap.printHeap();

        System.out.println("Max element: " + maxHeap.removeMax());
    }
}

8、最小堆:

package com.datastructure.heap;
//创建一个最小堆对象,初始化一个可以容纳10个元素的堆。
//实现插入元素、移除最小元素、维护堆性质等方法。
//在main方法中,向堆中插入了一些元素,并打印堆的内容。
//最后,移除最小元素并打印出来。
//这个例子中,数组heap的0索引是不使用的,实际数据存放从1索引开始。
//parent、leftChild和rightChild等方法用于计算给定位置的父节点和子节点在数组中的索引。
//这个实现的时间复杂度是O(log n),其中n是堆的大小。
public class MinHeap {

    private int[] heap;
    private int size;
    private int maxSize;

    private static final int FRONT = 1;

    public MinHeap(int maxSize) {
        this.maxSize = maxSize;
        this.size = 0;
        this.heap = new int[maxSize + 1];
        this.heap[0] = Integer.MIN_VALUE;
    }

    private int parent(int pos) {
        return pos / 2;
    }

    private int leftChild(int pos) {
        return 2 * pos;
    }

    private int rightChild(int pos) {
        return 2 * pos + 1;
    }

    private boolean isLeaf(int pos) {
        return pos >= size / 2 && pos <= size;
    }

    private void swap(int pos1, int pos2) {
        int temp = heap[pos1];
        heap[pos1] = heap[pos2];
        heap[pos2] = temp;
    }

    private void minHeapify(int pos) {
        if (!isLeaf(pos)) {
            if (heap[pos] > heap[leftChild(pos)] || heap[pos] > heap[rightChild(pos)]) {
                if (heap[leftChild(pos)] < heap[rightChild(pos)]) {
                    swap(pos, leftChild(pos));
                    minHeapify(leftChild(pos));
                } else {
                    swap(pos, rightChild(pos));
                    minHeapify(rightChild(pos));
                }
            }
        }
    }

    public void insert(int element) {
        if (size >= maxSize) {
            System.out.println("Heap is full");
            return;
        }

        heap[++size] = element;
        int current = size;

        while (heap[current] < heap[parent(current)]) {
            swap(current, parent(current));
            current = parent(current);
        }
    }

    public int removeMin() {
        if (size == 0) {
            return -1;
        }

        int min = heap[FRONT];
        heap[FRONT] = heap[size--];
        minHeapify(FRONT);

        return min;
    }

    public void printHeap() {
        for (int i = 1; i <= size / 2; i++) {
            System.out.print("Parent: " + heap[i] + ", Left Child: " +
                    heap[leftChild(i)] + ", Right Child: " + heap[rightChild(i)]);
            System.out.println();
        }
    }

    public static void main(String[] args) {
        MinHeap minHeap = new MinHeap(10);
        minHeap.insert(5);
        minHeap.insert(3);
        minHeap.insert(17);
        minHeap.insert(10);
        minHeap.insert(84);
        minHeap.insert(19);
        minHeap.insert(6);
        minHeap.insert(22);
        minHeap.insert(9);

        minHeap.printHeap();

        System.out.println("Min element: " + minHeap.removeMin());
    }
}

  • 17
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值