排序模板-1

1. 快速排序:

方法:快速排序就是先选中一个基准数,然后把比这个基准数小的数字移到基准数的左边,比基准数大的移到右边。

**特点**:
 - 快排的运行时间依赖于划分是否平衡,而平衡与否又依赖于用户划分的主元素。
 - 如果划分是平衡的,那么快速排序算法性能与归并排序一样。
 - 如果划分时不平衡的,那么快速排序的性能就接近于插入排序了
我们用来避免最差情况发生的方法如下:
**求序列的中值**,然后选取序列的中值作为轴元素
#中轴居中法:
    void quick_sort(int[] nums,int l,int r){//快速排序,l排序起始位置,r排序结束位置
        if(l>=r) return;
        int i=l-1,j=r+1;//为了在边界时满足循环判断条件
        int x=nums[(r-l)/2+l];//x是轴,轴是一个值,最终位置不定
        while(i<j){
            do i++;while(nums[i]<x);
            do j--;while(nums[j]>x);
            if(i<j){
                int temp=nums[i];
                nums[i]=nums[j];
                nums[j]=temp;
            }
        }
        quick_sort(nums,l,j);//中轴要落到j位置但是不一定落到j所以要再排序j
        quick_sort(nums,j+1,r);//j右边一定是比中轴大数
    }
 
 #最左边是初始轴法(填坑法)
    void quick_sort(int[] nums,int l,int r){//快速排序,l排序起始位置,r排序结束位置
        if(l>=r) return;
        int i=l,j=r;
        int x=nums[i];//x是轴,轴是一个值,最终位置不定(起初l是坑)
        while(i<j){
            while(i<j&&nums[j]>=x){
                j--;
            }
            nums[i]=nums[j];//填坑
            while(i<j&&nums[i]<=x){
                i++;
            }
            nums[j]=nums[i];
        }
        nums[i]=x;//轴归位
        quick_sort(nums,l,j-1);//中轴要落到j位置但是不一定落到j所以要再排序j
        quick_sort(nums,j+1,r);//j右边一定是比中轴大数
    }
  

2. 冒泡排序

方法:首先从数组的第一个元素开始到数组最后一个元素为止,对数组中相邻的两个元素进行比较,如果位于数组左端的元素大于数组右端的元素,则交换这两个元素在数组中的位置。这样操作后数组最右端的元素即为该数组中所有元素的最大值。接着对该数组除最右端的n-1个元素进行同样的操作,再接着对剩下的n-2个元素做同样的操作,直到整个数组有序排列。

时间复杂度:O(n)或O(n^2)

/* 冒泡排序 */
void BubbleSort(int[] arr, int length){
	for (int i = 0; i < length; i++){
		for (int j = 0; j < length -  i - 1; j++){
			if (arr[j] > arr[j + 1]){
				int temp= arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = temp;
			}
		}
	}
}

3. 选择排序

定义:每一趟选择一个最小的值,交换到指定位置
时间复杂度:O(n^2)

/* 选择排序 */
void SelectionSort(int[] arr){
    int index, temp,length=arr.length;
	for (int i = 0; i < length; i++){
        index = i;//最小值位置
		for (int j = i + 1; j < length; j++){
			if (arr[j] < arr[index])
				index = j;
		}
		if (index != i){//位置交换
			temp = arr[i];
			arr[i] = arr[index];
			arr[index] = temp;
		}
	}
}

4. 堆排序

    #建堆,将堆转换为有序数组
    public static void heapSort(int[] arr) {
        int temp=0;
        for(int i=arr.length/2-1;i>=0;i--){//构建好大根堆
            adjustHeap(arr,i,arr.length);
        }
        for(int j=arr.length-1;j>0;j--){//由大根堆变成排序好的数组
            temp=arr[j];
            arr[j]=arr[0];
            arr[0]=temp;
            adjustHeap(arr,0,j);
        }
    }
    #调整以i为根的树为大根堆
    public static void adjustHeap(int[] arr,int i,int length) {
        int temp=arr[i];//先取出当前元素的值,保存在临时变量
        for(int k=i*2+1;k<length;k=k*2+1) {//开始调整
            if(k+1<length && arr[k]<arr[k+1]) k++;//说明左子结点的值小于右子结点的值
            if(arr[k]>temp) {//如果子结点大于父结点
                arr[i]=arr[k];//把较大的值赋给当前结点
                i=k;//i指向k,继续循环比较
            }else  break;
        }
        //当for 循环结束后我们已经将以i为父结点的树的最大值,放在了最顶(局部)
        arr[i]=temp;//将temp值放到调整后的位置
    }

5. 希尔排序

定义:先将待排记录序列分割成为若干子序列分别进行插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行一次直接插入排序。
时间复杂度:n^(1.3—2))

    void ShellSort(int[] arr){
        int  len=arr.length,length=len;
        do{// 确定分组的增量
            len = len / 3 + 1;
            for (int i = 0; i < len; i++){
                for (int j = i + len; j < length; j += len){
                    if (arr[j] < arr[j - len]){
                        int temp = arr[j],k;
                        for (k = j - len; k >= 0 && temp < arr[k]; k -= len){
                            arr[k + len] = arr[k];
                        }
                        arr[k + len] = temp;
                    }
                }
            }
        } while (len > 1);
    }

6. 折半插入排序

    //折半插入排序
    public static void binaryInsertSort(int[] data){
        for(int i=1;i<data.length;i++){
            if(data[i] < data[i-1]){
                int tmp = data[i];//缓存i处的元素值
                int low = 0;//记录搜索范围的左边界
                int high = i-1;
                while(low <= high){
                    int mid = (low+high)/2;//记录中间位置
                    if(data[mid] < tmp){//比较中间位置数据和i处数据大小,以缩小搜索范围
                        low = mid +1;
                    }else
                        high = mid - 1;
                }
                for(int j = i;j>low;j--)//将low---i处的数据整体向后移动1位
                    data[j] = data[j-1];
                data[low] = tmp;
            }
        }
    }

7.归并排序

分治策略(将问题分成一些小的问题然后递归求解,而治的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
时间复杂度:O(nlogn)
空间复杂度:O(n)

    public ListNode sortList(ListNode head, ListNode tail) {//待排链表的头结点与尾节点
        if (head == null)
            return head;
        if (head.next == tail) {//如果只有两个节点,尾节点由另一个负责
            head.next = null;
            return head;
        }
        ListNode slow = head, fast = head;
        while (fast != tail) {//找到中间节点
            slow = slow.next;
            fast = fast.next;
            if (fast != tail)
                fast = fast.next;
        }
        ListNode mid = slow;
        ListNode list1 = sortList(head, mid);
        ListNode list2 = sortList(mid, tail);
        ListNode sorted = merge(list1, list2);
        return sorted;
    }
    public ListNode merge(ListNode head1, ListNode head2) {
        ListNode tHead = new ListNode(0);
        ListNode temp = tHead, temp1 = head1, temp2 = head2;
        while (temp1 != null && temp2 != null) {
            if (temp1.val <= temp2.val) {
                temp.next = temp1;
                temp1 = temp1.next;
            } else {
                temp.next = temp2;
                temp2 = temp2.next;
            }
            temp = temp.next;
        }
        if (temp1 != null) {
            temp.next = temp1;
        } else if (temp2 != null)
            temp.next = temp2;
        return tHead.next;
    }

8.基数排序

    //基数排序
    public static void radixSort(int[] arr) {
        int max=0;//得到数组中的最大数的小标,这样才能知道要循环多少轮
        for(int i=1;i<arr.length;i++) {
            if(arr[max]<arr[i]) {
                max=i;
            }
        }
        int times=(arr[max]+"").length();//得到数字共有几位数
        for(int time=0,n=1;time<times;time++,n*=10) {
            //创建桶,共有10个桶,每个桶最多有arr.length个数据
            int[][] bucket=new int[10][arr.length];
            //用于记录每个桶中有多少数据,用于遍历桶中的数据
            int[] bECount=new int[10];
            //开始遍历数组
            for(int i=0;i<arr.length;i++) {
                int digitOfElement=(int) ((arr[i]/n)%10); //取出对应的位数
                //将其存入bucket中
                bucket[digitOfElement][bECount[digitOfElement]]=arr[i];
                bECount[digitOfElement]++;
            }
            //将bucket中的数据输出到arr中
            int index=0;
            for(int i=0;i<bECount.length;i++) {
                if(bECount[i]!=0) {
                    for(int j=0;j<bECount[i];j++) {
                        arr[index]=bucket[i][j];
                        index++;
                    }
                }
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值