排序的算法

目录

数组

链表


数组

插入

public class charu {
    //维护一个有序的数组,新插入一个数,将它插入到合适的位置
    public static void sort(int a[]){
        for(int i=1;i<a.length;i++){
            int tmp=a[i];//待插入的数
            int j=i-1;
            while(j>=0&&a[j]>tmp){
                a[j+1]=a[j];
                j--;
            }
            a[j+1]=tmp;
            System.out.println();
            System.out.println("第"+i+"次");
            for(int ii=0;ii<a.length;ii++){
                System.out.printf("%d ",a[ii]);
            }
        }
    }
}

堆排序

package paixu.shuzu;

public class dui {
    public static void swap(int[] array, int index1, int index2) {
        int temp = array[index1];
        array[index1] = array[index2];
        array[index2] = temp;
    }
    // 最大堆
    public static void maxHeap(int[] array, int heapSieze, int index) {
        int left = index * 2 + 1; // 左子节点
        int right = index * 2 + 2; // 右子节点
        int maxValue = index; // 暂时定在Index的位置就是最大值

        // 如果左子节点的值,比当前最大的值大,就把最大值的位置换成左子节点的位置
        if (left < heapSieze && array[left] > array[maxValue]) {
            maxValue = left;
        }

        // 如果右子节点的值,比当前最大的值大,就把最大值的位置换成右子节点的位置
        if (right < heapSieze && array[right] > array[maxValue]) {
            maxValue = right;
        }

        // 如果不相等,说明啊,这个子节点的值有比自己大的,位置发生了交换了位置
        if (maxValue != index) {
            swap(array, index, maxValue); // 就要交换位置元素

            // 交换完位置后还需要判断子节点是否打破了最大堆的性质。最大堆性质:两个子节点都比父节点小。
            maxHeap(array, heapSieze, maxValue);
        }
    }
    // 构建堆
    public static void buildMaxHeap(int[] array) {
        if (array == null || array.length == 1)
            return;

        // 堆的公式就是 int root = 2*i, int left = 2*i+1, int right = 2*i+2;
        int cursor = array.length / 2;
        for (int i = cursor; i >= 0; i--) { // 这样for循环下,就可以第一次排序完成
            maxHeap(array, array.length, i);
        }
    }
    public static void sort(int[] array) {
        if (array == null || array.length == 1)
            return;

        buildMaxHeap(array); // 第一次排序,构建最大堆,只保证了堆顶元素是数组里最大的

        for (int i = array.length - 1; i >= 1; i--) {
            // 这个是什么意思呢?,经过上面的一些列操作,目前array[0]是当前数组里最大的元素,需要和末尾的元素交换
            // 然后,拿出最大的元素
            swap(array, 0, i);

            // 交换完后,下次遍历的时候,就应该跳过最后一个元素,也就是最大的那个值,然后开始重新构建最大堆
            // 堆的大小就减去1,然后从0的位置开始最大堆
            maxHeap(array, i, 0);
        }
    }
}

 归并

package paixu.shuzu;

public class guibing {
    //先对左右子数组排序,然后合并(类似合并有序链表的逻辑),你看这是不是二叉树的后序遍历框架

    //再说说归并排序的逻辑,若要对 nums[lo..hi] 进行排序,我们先对 nums[lo..mid] 排序,
    // 再对 nums[mid+1..hi] 排序,最后把这两个有序的子数组合并,整个数组就排好序了。

    public static void sort(int a[],int left,int right,int tmp[]){
        //o(n-1)
        if(left<right){
            int mid=(left+right)/2;
            //向左递归
            sort(a,left,mid,tmp);
            //向右递归
            sort(a,mid+1,right,tmp);
            merge(a,left,mid,right,tmp);
        }
    }
    //a排序原始数组
    //left左边有序序列的初始索引
    //mid中间索引
    //right右边索引
    //中转数组
    public static void merge(int a[],int left,int mid,int right,int tmp[]){
        int i=left;//左边有序序列的初始索引
        int j=mid+1;//右边有序序列的初始索引
        int t=0;//tmp数组的当前索引
        //先把左右两边的数据按照规则填充到tmp数组,直到左右两边序列,有一边处理完毕为止
        //把有剩余的一边的数据填充到tmp
        //tmp填充到a
        while(i<=mid&&j<=right){
            if(a[i]<=a[j]){
                tmp[t]=a[i];
                t++;
                i++;
            }else{
                tmp[t]=a[j];
                t++;
                j++;
            }
        }
        while (i<=mid){
            tmp[t]=a[i];
            t++;
            i++;
        }
        while (j<=right){
            tmp[t]=a[j];
            t++;
            j++;
        }

        //将tmp元素拷贝到a
        // 注意,不是每次都拷贝所有
        t=0;
        int tempLeft=left;
        while(tempLeft<=right){
            a[tempLeft]=tmp[t];
            tempLeft++;
            t++;
        }
    }
}

快速

package paixu.shuzu;

public class kuaisu {
    //先构造分界点,然后去左右子数组构造分界点,你看这不就是一个二叉树的前序遍历吗
    //快速排序的逻辑是,若要对 nums[lo..hi] 进行排序,我们先找一个分界点 p,
    // 通过交换元素使得 nums[lo..p-1] 都小于等于 nums[p],且 nums[p+1..hi] 都大于 nums[p],
    // 然后递归地去 nums[lo..p-1] 和 nums[p+1..hi] 中寻找新的分界点,最后整个数组就被排序了
    public static void sort(int a[],int left,int right){
        int l=left;
        int r=right;
        int pivot=a[(l+r)/2];
        int tmp=0;
        //while循环目的是让比pivot小的放左边,大的放右边
        while(l<r){
            while (a[l]<pivot){
                l++;
            }
            //在mid右边找,找到小于等于a[mid]的值
            while (a[r]>pivot){
                r--;
            }

            //l>=r说明左右两的值,以及全部按照左边小于pivot,右边大于pivot排好序
            if(l>=r){
                break;
            }
            tmp=a[l];
            a[l]=a[r];
            a[r]=tmp;
            //交换完,发现相等,为了避免陷入死循环
            if(a[l]==pivot){
                r--;
            }
            if(a[r]==pivot){
                l++;
            }
        }
        if(l==r){
            l+=1;
            r-=1;
        }
        if(left<r)
            sort(a,left,r);
        if(right>l)
            sort(a,l,right);
    }
}

 冒泡

package paixu.shuzu;

public class maopao {
    //0-N-1  两两比较,交换,使每一轮交换后最大值逐步移到最后
    public static void sort(int a[]){
        for(int i=0;i<a.length;i++){
            for(int j=0;j<a.length-i-1;j++){
                if(a[j]>a[j+1]){
                    int tmp=a[j];
                    a[j]=a[j+1];
                    a[j+1]=tmp;
                }
            }
            System.out.println("第"+i+"次");
            for(int ii=0;ii<a.length;ii++){
                System.out.printf("%d ",a[ii]);
            }
        }
    }
}

选择

package paixu.shuzu;

public class xuanze {
    //0-N-1 找最小值,放到0位置
    //1-N-1 找最小值,放到1位置
    public static void sort(int a[]) {
        for (int i = 0; i < a.length - 1; i++) {
            int index = i;
            for (int j = i + 1; j < a.length; j++) {
                if (a[index] > a[j]) {
                    index = j;
                }
            }
            if (index != i) {
                int tmp = a[i];
                a[i] = a[index];
                a[index] = tmp;
            }
        }
    }
}

 

链表

冒泡排序

class ListNode {
    int val;
    ListNode next;
    ListNode() {
    }
    ListNode(int val) {
        this.val = val;
    }
    ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}
public class maopao {
    public static ListNode bubbleSort(ListNode head){
        if(head == null || head.next == null)  //链表为空或者仅有单个结点
            return head;
        ListNode cur = null, tail = null;
        cur = head;
        while(cur.next != tail){
            while(cur.next != tail){
                if(cur.val > cur.next.val){
                    int tmp = cur.val;
                    cur.val = cur.next.val;
                    cur.next.val = tmp;
                }
                cur = cur.next;
            }
            tail = cur;  //下一次遍历的尾结点是当前结点(仔细琢磨一下里面的道道)
            cur = head;     //遍历起始结点重置为头结点
        }

        return head;
    }
}

 归并

public class guibing {
    //归并排序
    public static ListNode mergeSort(ListNode head){
        if(head == null || head.next == null)  //空链表或者只有单个结点
            return head;
        ListNode slow = head, fast = head.next;

        while(fast != null && fast.next != null){  //使用快慢指针寻找中间 结点
            slow = slow.next;

            fast = fast.next;
            if(fast.next != null)
                fast = fast.next;
        }

        ListNode ptr1 = slow.next;
        slow.next = null;

        ListNode tmp1 = mergeSort(head);
        ListNode tmp2 = mergeSort(ptr1);
        return merge(tmp1, tmp2);
    }
    public static ListNode merge(ListNode start1,  ListNode start2){
        ListNode header = new ListNode(-1);
        ListNode pre = header;
        ListNode ptr1 = start1, ptr2 = start2;
        while(ptr1 != null && ptr2 != null){
            if(ptr1.val <= ptr2.val){
                pre.next = ptr1;
                pre = ptr1;
                ptr1 = ptr1.next;
            }else{
                pre.next = ptr2;
                pre = ptr2;
                ptr2 = ptr2.next;
            }
        }
        while(ptr1 != null){
            pre.next = ptr1;
            pre = ptr1;
            ptr1 = ptr1.next;
        }
        while(ptr2 != null){
            pre.next = ptr2;
            pre = ptr2;
            ptr2 = ptr2.next;
        }
        return header.next;
    }
}

快排

public class kuaipai {
    //快速排序
    public static void quickSort(ListNode begin, ListNode end){
        if(begin == null || begin == end)
            return;

        ListNode index = paration(begin, end);
        quickSort(begin, index);
        quickSort(index.next, end);
    }

    /**
     * 划分函数,以头结点值为基准元素进行划分
     * @param begin
     * @param end
     * @return
     */
    public static ListNode paration(ListNode begin, ListNode end){
        if(begin == null || begin == end)
            return begin;

        int val = begin.val;  //基准元素
        ListNode index = begin, cur = begin.next;

        while(cur != end){
            if(cur.val < val){  //交换
                index = index.next;
                int tmp = cur.val;
                cur.val = index.val;
                index.val = tmp;
            }
            cur = cur.next;
        }


        begin.val = index.val;
        index.val = val;

        return index;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值