数据结构小测试:排序算法

目录

1、请简述数据结构八大排序算法的思路。

2、常用排序算法手写

冒泡排序:

选择排序:

快速排序:

归并排序:

堆排序:

3、额外再加一个二分查找吧


1、请简述数据结构八大排序算法的思路。

冒泡排序:将相邻元素之间的比较和交换,使得每一轮比较后,最大的元素能够到达数组的末尾。重复这个过程,直到整个数组有序。

选择排序:在每一轮中,找到数组中最小的元素,并将其与当前轮的第一个元素交换位置。重复这一操作,使得每一轮过后,都有一个元素被放到了正确的位置上。

插入排序:将数组分为已排序部分和未排序部分,每次从未排序部分取出一个元素,插入到已排序部分的正确位置上。

希尔排序:首先确定一个间隔序列,按此间隔将数组元素分组并进行插入排序。随后逐渐缩小间隔并重复排序过程,直到间隔为1。

快速排序:选一个基准元素,通过一趟排序将整体数据分割成两部分,基准元素左边的数据比基准元素小,右边的数据比基准元素大,然后再按此方法对这两部分数据分别进行快速排序,递归进行,直至完成。

归并排序:先将数组分成两半,分别对这两半进行排序,然后将它们合并成一个有序数组。重复递归这一操作,直至数组有序

堆排序:将待排序的序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个序列重新构造成一个堆,这样会得到n个元素中的次大值。重复以上操作。

计数排序:对输入数据中的每个元素进行计数,确定每个元素出现的次数;然后利用计数结果将元素放到输出序列的正确位置上。

2、常用排序算法手写

冒泡排序:

将相邻元素之间的比较和交换,使得每一轮比较后,最大的元素能够到达数组的末尾。重复这个过程,直到整个数组有序。时间复杂度:O(n^2)

代码:

public static void sort(int[] arr) {
        for(int j=0;j<arr.length;j++) {
            for(int i=0;i<arr.length-1-j;i++) {
                if(arr[i]>arr[i+1]) {
                    int temp=arr[i];
                    arr[i] =arr[i+1];
                    arr[i+1]=temp;
                }
            }
        }
    }

选择排序:

在每一轮中,找到数组中最小的元素,并将其与当前轮的第一个元素交换位置。重复这一操作,使得每一轮过后,都有一个元素被放到了正确的位置上。 时间复杂度:O(nlogn)

代码:

public static void simpleswap(int[] arr) {
    for(int i=0; i<arr.length; i++) {  //负责遍历索引
        int index =i ;//index负责找最小的索引
        for(int j=i+1; j<arr.length; j++) { //负责找剩余元素中的最小值
            if(arr[j]<arr[index]) {
                index = j;
            }
        }
        //每找到一次就与前面的交换一次
        if(i != index){
            int temp = arr[index];
            arr[index] = arr[i];
            arr[i] = temp;
        }
    }
}

快速排序:

选一个基准元素,通过一趟排序将整体数据分割成两部分,基准元素左边的数据比基准元素小,右边的数据比基准元素大,然后再按此方法对这两部分数据分别进行快速排序,递归进行,直至完成。

时间复杂度:O(nlogn)

代码:

public static void quicksort(int[] arr,int left,int right) {
        //递归出口
        if(left>=right) {
            return;
        }
        //定义变量保存基准数
        int base=arr[left];
        //定义j游标指向最右边
        int j=right;
        //定义i游标指向最左边
        int i=left;
        while(i!=j) {
            //j从后往前找比基准数小的
            while(arr[j]>=base&&i<j) {
                j--;
            }
            //i从前往后找比基准数大的
            while(arr[i]<=base&&i<j) {
                i++;
            }
            //i、j两数都停下,交换位置
            int temp=arr[i];
            arr[i]=arr[j];
            arr[j]=temp;
            
        }
        //i和j相等(跳出循环)
        //交换基数和ij相遇位置的数据
        arr[left]=arr[i];
        arr[i]=base;
        //排序基准数的左边
        quicksort(arr,left,i-1);
        //排序基准数的右边
        quicksort(arr,i+1,right);
        
    }

归并排序:

先将数组分成两半,分别对这两半进行排序,然后将它们合并成一个有序数组。重复递归这一操作,直至数组有序。时间复杂度:O(nlogn)

底层逻辑:先拆分,拆到不能再拆分,然后进行合并,合并的时候进行排序

代码: 

public class MergeSort {
    public static void main(String[] args) {
        int[] nums = new int[] { 9, 8, 7, 6, 5, 4, 3, 2, 10 };
        int[] newNums = mergeSort(nums, 0, nums.length - 1);
        System.out.println(Arrays.toString(newNums));
    }

    public static int[] mergeSort(int[] nums, int left, int right) {
        if (left == right)//已经拆分彻底,拆分递归的终止条件
            return new int[] { nums[left] };

        //拆分
        int mid = left + (right - left) / 2;
        int[] leftArr = mergeSort(nums, left, mid); //左有序数组
        int[] rightArr = mergeSort(nums, mid + 1, right); //右有序数组
        int[] newNum = new int[leftArr.length + rightArr.length]; //新有序数组

        //合并,将拆分的数按大小放到新有序数组里面
        int m = 0, i = 0, j = 0;
        while (i < leftArr.length && j < rightArr.length) {
            newNum[m++] = leftArr[i] < rightArr[j] ? leftArr[i++] : rightArr[j++];
        }
        while (i < leftArr.length)
            newNum[m++] = leftArr[i++];
        while (j < rightArr.length)
            newNum[m++] = rightArr[j++];
        return newNum;
    }
}

堆排序:

利用完全二叉树构建大顶堆,此时,整个序列的最大值就是堆顶的根节点。

将堆顶元素与堆底元素进行交换,此时堆底元素就为最大值。

然后将剩余n-1个序列重新构造成一个大顶堆。重复以上操作。

时间复杂度:O(nlogn)

大顶堆:父节点的值大于等于其左右孩子的值 等价于 arr[i]>=arr[2i+1] && arr[i]>=arr[2i+2]

流程图示:

构建大顶堆:

堆顶元素与堆底元素交换,堆底元素不再参与构建,剩下的再次重新构建大顶堆、交换

这一次重新构建时,直接让parent指向堆顶元素,再判断即可

java代码:


public class 堆排序 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr= {5,7,4,2,0,3,1,6};
		//1、构建大顶堆
		for(int i=arr.length-1;i>=0;i--) {//从下往上,每个节点以此判断为大顶堆;从length-1节点到0节点
			adjust(arr,i,arr.length);
		}
		System.out.println(Arrays.toString(arr));//输出第一次构建的大顶堆
		
		//2、堆顶堆底元素交换,除堆底外其余元素继续构建大顶堆
		for(int j=arr.length-1;j>=0;j--) {
			
			int temp=arr[j];
			arr[j]=arr[0];
			arr[0]=temp;
			//System.out.println(Arrays.toString(arr));
			
			//剩余元素继续构建大顶堆
			adjust(arr,0,j);//parent游标直接指向堆顶元素即可,最后一个元素不再参与构建
			//System.out.println(Arrays.toString(arr));
		}
		System.out.println(Arrays.toString(arr));
		
	}
	
	public static void adjust(int[] arr,int parent,int length) {
		int child = parent*2+1;//定义左孩子
		while(child<length) {//如果有孩子节点
			int rchild=child+1;//定义右孩子
			//这部分单纯为了让child指向最大child
			if(rchild<length && arr[child]<arr[rchild]) {//如果有右孩子,且右孩子比较大
				child++;//child指向较大的孩子节点(右孩子节点)
			}
			
			//如果父节点小于其孩子节点
			if(arr[parent]<arr[child]) {
				int temp=arr[parent];
				arr[parent]=arr[child];
				arr[child]=temp;
				
				//父子结点交换后parent指向child
				parent=child;
				child=2*parent+1;
				//再次进行循环比较
			}else {//如果该parent没有孩子节点或者父节点大于孩子节点,直接返回,此节点判断完毕
				break;
			}
		}
	}

}

3、额外再加一个二分查找吧

时间复杂度:O(logn)

代码:

public class 二分查找 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr= {3,45,56,57,67,88};
		System.out.println(search(arr,11));
		
	}
	public static int search(int[] arr,int target) {
		int left = 0;
		int right = arr.length-1;
		
		while(left<=right) {
			int middle = (left+right)/2;
			if(target==arr[middle]) {
				System.out.println("找到了");
				return middle;
			}else if(target<arr[middle]){
				right=middle-1;
			}else {
				left=middle+1;
			}
		}
		
	System.out.println("没有这个数据");
	return -1;
	}

}

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-16 08:16:04       70 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-16 08:16:04       74 阅读
  3. 在Django里面运行非项目文件

    2024-07-16 08:16:04       62 阅读
  4. Python语言-面向对象

    2024-07-16 08:16:04       72 阅读

热门阅读

  1. Gmsh教程

    2024-07-16 08:16:04       31 阅读
  2. Redis是什么

    2024-07-16 08:16:04       28 阅读
  3. 机器学习——机器学习概述

    2024-07-16 08:16:04       21 阅读
  4. 深入理解 Vue.js 的生命周期:从创建到销毁

    2024-07-16 08:16:04       27 阅读
  5. 2024.7.10 day 3 比赛总结

    2024-07-16 08:16:04       20 阅读
  6. 大模型 GPT 到 GPT-3.5 知识点总结

    2024-07-16 08:16:04       23 阅读
  7. Python 和 R两者的主要区别和优缺点对比

    2024-07-16 08:16:04       26 阅读
  8. k8s怎么配置secret呢?

    2024-07-16 08:16:04       24 阅读
  9. vue $refs

    2024-07-16 08:16:04       24 阅读
  10. 【php开发系统遇到CPU飙升的思考记录】

    2024-07-16 08:16:04       27 阅读