欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第一章

程序员文章站 2022-06-13 20:06:03
...

第一章

时间复杂度

排序

交换函数

	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

冒泡

时间复杂度 O(n^2),额外空间复杂度O(1),可以做到稳定排序。

public static void bubbleSort(int [] arr)
{
	if(arr==null||arr.lenth<2)
	{
		return;
	}
	for(int  i=0;i<arr.lenth-1;i++)
	{
		for(int j=0;j<n-i-1;j++)
		{
			if(a[i]>a[i+1])
			{
				swap(arr,i,i+1);
			}
		}
	}
	
}

逆序冒泡

    public static void dubbleSort(int [] arr)
    {
        for (int i=arr.length-1;i>0;i--)
        {
            //逆序比较
            for (int j=0;j<i;j++)
            {
                if (arr[j]>a[j+1])
                    //每两个比较一次 
                    swap(arr,j,j+1);
                
            }
            //第一趟排序中  0-n上全局最大值已经放在了最后
            //从  0----n-1 上继续比较
            //从  0----n-2  继续比较
        }
    }
    //54321
    //43215
    //32145
    //21345
    //12345    

对数器

用于判断流程是否正确

	public static int[] generateRandomArray(int maxSize, int maxValue) {

       //

		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];

		for (int i = 0; i < arr.length; i++) {

			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());

		}

		return arr;

	}

直接插入排序

最好 o(n) 最坏 o(n^2)辅助空间O(1)

优点是实现简单,不占用多余空间,但效率较低,并且经常需要交换数据。

	public static void insertionSort(int[] arr) {
	if (arr == null || arr.length < 2) {
		return;
	}
	for (int i = 0; i < arr.length-1; i++) {
		for (int j = i; j >= 0 && arr[j] > arr[j + 1]; j--) {
			//每次比较前一位数是否大于当前数   一直循环到  arr[0]
			swap(arr, j, j + 1);
		}
	}
}
//外循环为
6324
    3624
    
    3264
    2364
    
    2346
    

外循环是 arr.lenth 假如数组中有5个元素,则 lenth=5,考虑到内循环是两两比较,并且每次要判断当前数与前面一个数进行比较。

每次比较将当前序列中的最大数放到最后,内层循环 j -1,如果 j=0 ,继续判断 a[j] 与 a[j+1]的关系,当j=-1<0时,停止循环。

外循环为0,循环到lenth-1. 内循环为i,循环到0。

选择排序

	public static void selectionSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}
		for (int i = 0; i < arr.length - 1; i++) {
			int minIndex = i;
			for (int j = i + 1; j < arr.length; j++) {
				minIndex = arr[j] < arr[minIndex] ? j : minIndex;
			}
			swap(arr, i, minIndex);
		}
	}

三大排序 时间复杂度O(N*logN)

归并排序 空间复杂度O(N)

	public static void mergeSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}
		mergeSort(arr, 0, arr.length - 1);
	}

	public static void mergeSort(int[] arr, int l, int r) {
		if (l == r) {
			return;
		}
		int mid = l + ((r - l) >> 1);
		mergeSort(arr, l, mid);//左边排好
		mergeSort(arr, mid + 1, r);//右边排 好
		merge(arr, l, mid, r);//一起排 
	}

	public static void merge(int[] arr, int l, int m, int r) {
		int[] help = new int[r - l + 1];
		int i = 0;
		int p1 = l;
		int p2 = m + 1;
		while (p1 <= m && p2 <= r) {
			help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
		}
        //将新的数据进行比较  小的放进数据
		while (p1 <= m) {
			help[i++] = arr[p1++];
		}
		while (p2 <= r) {
			help[i++] = arr[p2++];
		}
		for (i = 0; i < help.length; i++) {
			arr[l + i] = help[i];
		}
	}

递归时间复杂度

T(n)= 2 * T(N/2) +O(N)

计算公式:

第一章

快速排序O(log N)

经典排序

直接选定最后一个数为基准数,小于等于基准数的放左边,大于的放右边,只是实现了一定程度的有序,没有实现从小到大或者从大到小的顺序。

//经典快排
public static int partition(int [] arr,int L,int R)
{
	int p=a[R];
	int less=L-1;
	for(int i=0; i <=R;i++)
	{
		if(a[i]<=p)
		{
			swap(arr,++less,i);
		}
	}
 return less;
    //返回分界位置
} 

建立小于区的概念,该区的位置一开始是 -1;

a[i] <=p (最后一个数)

将小于区的下一个数 与当前数进行交换,i++

随机快速排序

	public static void quickSort(int[] arr, int l, int r) {
		if (l < r) {
			swap(arr, l + (int) (Math.random() * (r - l + 1)), r);
            //随机选择一个数作为排序指标,将这个数与最后一个数进行交换
			int[] p = partition(arr, l, r);
			quickSort(arr, l, p[0] - 1);
            //p[0]为等于区的第一个位置  p[0]-1为等于区的前一个位置
			quickSort(arr, p[1] + 1, r);
            //p[1]为等于区的最后一个位置  p[1]+1为等于区的最后一个位置的下一个位置
		}
	}
	public static int[] partition(int[] arr, int l, int r) {
		int less = l - 1;
		int more = r;
		while (l < more) {
			if (arr[l] < arr[r]) {
			    	swap(arr, ++less, l++);
			} else if (arr[l] > arr[r]) {
				swap(arr, --more, l);
			} else {
				l++;
			}
		}
		swap(arr, more, r);
		return new int[] { less + 1, more };
        //返回的是等于区的范围
	}
	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

荷兰国旗问题

第一章

	public static int partition2(int [] a,int L,int R)
	{
 		int max=R;
		int min=L-1;
		int t=a[R];
		while(L<max)
		{
			if(a[L]<t)
			{
				swap(a,++min,L++);
			}
			else if(a[L]>t)
			{
				swap(a,--max,L);
			}
			else 
			{
				L++;
			}
			swap(a,max,R);
		}
	}

建立3个区,一个小于num的小于区,一个等于区,一个大于num的大于区。(下面的指针只是代表指向,不是真正的指针)

建立两个指针,一个指向数组的最后一个数,一个指向数组第一个数的前一个数,从第一个数开始遍历,每遍历一个数会有三种情况。

小于num

当前数与小于区的下一个数交换

小于区指针往后一个

指针指向下一个数

等于num

不动,指针指向下一个数

大于num

与大于区的前一个数进行交换 大于区向前指向一个数

指针不动 继续判断指针指向的数

如果此数小于num 将它于小于区的下一个数进行交换

如果=num 不动 指针向后一位

如果大于 与大于区的前一个数进行交换 大于区向前指向一个数

当指针指向遇到 大于区的指针 循环停止

判断大于区最右边的数是否大于num 如果大于 不动

堆排序O(1)

待补充

排序稳定性

排序的稳定性指的是,每次排序之后数值相同的数的相对位置基本不发生改变

比如 4 3 2 2 1 1 ,从小到大排序之后是:

1 1 2 2 3 4 这里的每个重复的数 都能相对于原来的位置不变,这里的第一个1 是原来序列中倒数第二个1,新序列的第二个1 ,是原来序列的倒数第一个1.

于num 将它于小于区的下一个数进行交换

如果=num 不动 指针向后一位

如果大于 与大于区的前一个数进行交换 大于区向前指向一个数

当指针指向遇到 大于区的指针 循环停止

判断大于区最右边的数是否大于num 如果大于 不动

堆排序O(1)

待补充

排序稳定性

排序的稳定性指的是,每次排序之后数值相同的数的相对位置基本不发生改变

比如 4 3 2 2 1 1 ,从小到大排序之后是:

1 1 2 2 3 4 这里的每个重复的数 都能相对于原来的位置不变,这里的第一个1 是原来序列中倒数第二个1,新序列的第二个1 ,是原来序列的倒数第一个1.