排序算法总结

一.冒泡排序

1 思想

冒泡排序是使用第一个值和后续列表中的所有值进行比较,如果大于后续列表中的值那就进行位置的交换。
第一个值排好之后,使用第二个值与后续的值进行比较,如果大于后续列表中的值那就进行位置的交换。
第二个值排好之后,使用第三个值与后续的值进行比较,依次循环确定好每一个位置上的值。
当然 x个数只需要排 x - 1次
时间复杂度O(n²)·

2 代码流程


public static int[] popSortStep(int[] arr){
	// 第一次排序
	// 使用第一个位置上的值和后续的值进行比较
	for(int i = 0 ,j = 1; j < arr.length; j++){
		if(arr[i] > arr[j]){
			int temp = arr[i];
			arr[i] = arr[j]
			arr[j] = temp
		}
	}

	// 第二次排序
	// 使用第二个位置上的值与后续值进行比较
	for(int i = 1,j = 2; j < arr.length ; j++){
		if(arr[i] > arr[j]){
			int temp = arr[i];
			arr[i] = arr[j];
			arr[j] = temp;
		}	
	}
	
	// 后续的排序依旧按照这个顺序来 i=2,j=i+1
	return arr;
}


3.完整代码


public static int[] popSort(int[] arr){
	// 排序的次数是数组元素个数 - 1
	for(int i = 0 ;  i < arr.length - 1 ; i++){
		for(int j = i+1 ; j < arr.length ; j++){
			if(arr[i] > arr[j]){
				int temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
		}
	}
	return arr;
}


二.选择排序

1.思想

我们使用两个变量比如min和minIndex用来记录当前数组中的最小值和最小值的数组下标位置
先默认数组中的第一个值是最小的。然后使用min依次与后续的值比较,如果发现min大于后续列表中的值,
那就改变min和minIndex的值为较小一个的值。(这里就是与冒泡不同的地方,冒泡排序是发现小于当前值的话会直接交换,
而选择排序是选择记录的方式),当遍历完成后才判断minIndex是否改变了,如果改变了就进行交换。
第一次遍历完就确定将我们最小的值放到了列表的第一个位置。
然后开始对第二个值进行以上的操作。
时间复杂度O(n²)

2.代码流程


public static int[] selectSortStep(int[] arr){
	// 第一次排序
	// 先定下第一个位置上的值
	// 先默认数组的第一个位置上的值是最小的
	int min = arr[0];
	int minIndex = 0;

	// 使用这个最小值与后续值进行比较
	for(int j = 1 ; j < arr.length - 1 ; j++){
		// 如果当前的认定的最小值大于后面的值,就进行改变min,minIndex的值
		if(min > arr[j]){
			min = arr[j];
			minIndex = i;
		}
	}

	// 遍历完成后,可以判断数组第一个位置的值是否是最小的,不是就进行交换
	if(minIndex != 0){
		arr[minIndex] = arr[0];
		arr[0] = min;
	}


	// 第二次排序
	// 确定第二个位置上的值
	// 先默认数组的第二个位置上的值是最小的
	min = arr[1];
	minIndex = 1;

	for(int j = 2 ; j < arr.length - 1 ; j++){
		
		if(min > arr[j]){
			min = arr[j];
			minIndex = i;
		}
	}

	if(minIndex != 1){
		arr[minIndex] = arr[1];
		arr[0] = min;
	}
	
	return arr;
	
}

3.完整代码


public static int[] selectSort(int[] arr){
	// 这里排序的次数也是数组元素个数-1
	for(int i = 0 ; i < arr.length - 1 ; i++){
		int min = arr[i];
		int minIndex = i;

		for(int j = i + 1; j < arr.length ; j++){
			if(min > arr[j]){
				min = arr[j];
				minIndex = i;
			}
		}
		
		if(minIndex != i){
			arr[minIndex] = arr[i];
			arr[i] = min;
		}

	}
	
return arr;
} 


三.插入排序

1.思想

我们将待排序的数组看成两部分,一部分是有序的,一部分是无序的,将无序的数组中的元素插入到有序数组中去,直到无序的数组中没有任何一个元素。
把 n 个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有 n-1 个元素
比如:我们将数组的第一个元素看成是一个有序的,后面的元素都是无序的。在这里插入图片描述

2.代码流程


public void static sortOne(int[] arr){
	// 第一次排序
	// 记录数组中的当前值
	int insertVal = arr[1];
	// 记录当前值要插入位置的前一个元素
	int insertIndex = 1 - 1;
	
	// 通过循环来找到我们要插入值的位置
	// 当insertIndex小于0时,说明已经到达了第一个位置
	// 当insertVal > arr[insertIndex]时。说明已经找到了当前值的一个合适位置
	while(insertIndex >= 0 && insertVal < arr[insertIndex]){
		// 将前一个值后移
		arr[insertIndex+1] = arr[insertIndex];
		
		// 将记录要插入位置的指针前移
		insertIndex--;
	}
	// 当循环结束后,要么是达到了第一个位置,要么是已经找到了合适的位置
	arr[insertIndex+1] = indexVal;

	// 第二次排序
	 insertVal = arr[2];
	 insertIndex = 2 - 1;
	
	while(insertIndex >= 0 && insertVal < arr[insertIndex]){
		arr[insertIndex+1] = arr[insertIndex];
		insertIndex--;
	}

	arr[insertIndex+1] = indexVal;

}

3.完整代码

public static void sortInsert(int[] arr){
	
	// 进入循环,从第二个值开始
	for(int i = 1 ; i< arr.length ; i++){
		// 记录当前值
		int insertVal = arr[i];
		// 记录要插入位置的前一个值
		int insertIndex = i - 1;

		while(insertIndex >= 0 && insertVal < arr[insertIndex]){
			arr[insertIndex+1] = arr[insertIndex];
			insertIndex--;
		}
		
		// 跳出while循环后,说明已经找到合适的插入位置
		// 优化方案,如果当前值的最佳位置就是当前位置的话,那么就不用进行交换,反之,则要交换
		if(insertIndex + 1 != i){
			arr[insertIndex + 1] = insertVal;
		}
	}

}

四.希尔排序

1.思想

我们将要排序的数组进行一个分组的操作,比如一共10个元素,10/2=5,把数组分成5组,每组两个元素,分别进行排序。当排序完一次后,再进行分组 5/2=2,分成两组的形式,再进行排序。最后2/2=1,最后再进行整个组内的排序。

在这里插入图片描述

2.代码流程


public static void sortOne(int[] arr){
	// 我们假设数组的长度是10
	// 第一次排序
	int gap = 5 // 10/2

 	// 分为5个组,初始增量是5
	for(int i = gap ; i < arr.length ; i++){
		//j的循环是一个插入排序,和前面的有序数组进行比较。
		// 先和后面的值进行比较,再和前面的值进行比较
		for(int j = i - gap ; j >= 0 ; j -=gap){
			if(arr[j] > arr[j + gap]){
				int temp = arr[j];
				arr[j] = arr[j + gap];
				arr[j+gap] = temp;
			}
		}
		
	}

	// 第二次排序
	int gap = 5/2 // 10/2

 	// 分为2个组,初始增量是2
	for(int i = gap ; i < arr.length ; i++){
		//让一个元素和其前面的元素进行比较
		for(int j = i - gap ; j >= 0 ; j -=gap){
			if(arr[j] > arr[j + gap]){
				int temp = arr[j];
				arr[j] = arr[j + gap];
				arr[j+gap] = temp;
			}
		}
		


}

3.完整代码


public void static sortShell(int[] arr){
	// 增量的循环
	for(int gap = arr,length / 2 ; gap > 0 ; gap /= 2){
		
		for(int i = gap ; i < arr,length ; i++){
			for(int j = i- gap; j >= 0 ; j-= gap){
				if(arr[j] > arr[j+gap] ){
					int temp = arr[j];
					arr[j] = arr[j + gap];
					arr[j+gap] = temp;
				}
			}
		}	

	}
}

五.快速排序

1.思想

是冒泡排序法的改进方案,以中间的节点为基准,小于中间节点的放在左边,大于中间节点的放在右边。
先找到左边比中间节点大的值,再找到右边比中间节点小的值,然后进行交换位置。
当我们的左指针到了中间,右指针也到了中间,那就使用递归,改变中间值。
使用递归的方式依次进行排序。

2.代码流程

public static void sortOne(int[] arr,int left , int right){
	// 记录当前数组中最左边的值
	int l = left;
	// 记录当前数组中最右边的值
	int r = right;
	// 记录当前数组中间的节点位置
	int mid = (r+l)/2;
	// 一个临时的值,用来交换使用
	int tenmp = 0;

	while(l > r){
		// 这个循环是为了找到比中间节点大的值
		while(arr[l] < arr[mid]){
			l++;
		}

		// 这个循环是为了找到比中间节点小的值
		while(arr[r] > arr[mid]){
			r--;
		}

		// 判断是不是都是到了中间了,大于就要退出了
		if(l >=r){
			break;
		}

		// 进行左右值的交换
		temp = arr[l];
		arr[l] = arr[r];
		arr[r] = temp;


		// 如果这时候左边的指针达到了中间,那么就将右边的指针移动
		if(l == mid){
			r--;
		}
		// 如果这时候右边的指针达到了中间,那么就将左边的指针移动
		if(r == mid){
			l++;
		}
		
	}	
}


3.完整代码

public static void quickSort(int[] arr,int left , int right){
	// 当前数组中最右边的指针
	int l = left;
	// 当前数组中最左边的指针
	int r = right;
	// 设置当前数组中的中间节点
	int mid = (l+r)/2;

	while(l < r){
		// 开始找左边比中间值大的数
		while(arr[l] < arr[mid]){
			l++;
		}
		// 开始找右边比中间值小的数
		while(arr[r] > arr[mid]){
			r--;	
		}

		// 判断r和l是否都已经到中间了,到了就结束循环
		if(l >= r){
			break;
		}
		
		// 进行交换位置
		temp = arr[l];
		arr[l] = arr[r];
		arr[r] = temp;

		// 如果左边的指针到了中间,那么就移动右边的指针
		if(l == mid){
			r--;
		}
		// 如果右边的指针到了中间,那么就移动左边的指针
		if(r == mid){
			l++;
		}
	}
	//开始向左向右递归排序
	// 如果两个值都在中间的话,就各自移动一位
	if(l == r){
		l--;
		r++;
	}
	
	// 向左递归
	if(l < right){
		quickSort(arr,l,right);
	}

	// 向右递归
	if(left < r){
		quickSort(arr,left,r);
	}

}


六.归并排序

1.思想

归并排序就是使用的分治算法,先将数组化整为零,将数组分为一个个的数,
然后再合并,将数组中的数从小到大的放到一个临时数组中。最后再放回原本的数组中。
在这里插入图片描述

2.合并的代码流程

public static void merge(int[] arr,int left , int mid , int right,int[] temp){
	// 左边的初始索引
	int l = left;
	// 右边的初始索引
	int r = mid + 1;
	// 临时数组中的索引
	int tempIndex = 0;

	// 先将一个数组中的数放到临时数组中
	while(l <= mid && r <= right){
		// 如果左边的值小,那么就将左边的值放入到临时数组中
		if(arr[l] < arr[r]){
			temp[tempIndex] = arr[l];
			l++;
			tempIndex++;
		}
		// 如果右边的值小,那么就将右边的值放入到临时数组中
		if(arr[r] < arr[l]){
			temp[tempIndex] = arr[r];
			r++;
			tempIndex++;
		}		
	}

	// 退出循环后,说明有一个数组中的值已经全部添加到临时数组中
	// 接下来将另外一个数组中的值添加到临时数组中
	while(l <= mid){
		temp[tempIndex] = arr[l];
		l++;
		tempIndex++;
	}
	while(r <= right){
		temp[tempIndex] = arr[r];
		r++;
		tempIndex++;
	}

	// 接下来就将临时数组中的值放入到原始数组中
	// 设置原始数组中的下标
	int leftIndex = left;
	// 将临时数组中的下标初始化
	tempIndex = 0;

	// 将临时数组中的值放到原始数组中
	while(leftIndex <= right){
		arr[leftIndex] = temp[tempIndex];
		leftIndex++;
		tempIndex++;
	}

}


3.完整代码

public static void mergeSort(int[] arr,int left,int right,int[] temp){
	if(left  < right){
		int mid = (left+right)/2;

		// 向左分解
		mergeSort(arr,left,mid,temp);
		// 向右分解
		mergeSort(arr,mid + 1 , right,temp);

		// 开始合并
		merge(arr,left,mid,right,temp);
	}

}

public static void merge(int[] arr,int left , int mid , int right,int[] temp){
	// 左边的初始索引
	int l = left;
	// 右边的初始索引
	int r = mid + 1;
	// 临时数组中的索引
	int tempIndex = 0;

	// 先将一个数组中的数放到临时数组中
	while(l <= mid && r <= right){
		// 如果左边的值小,那么就将左边的值放入到临时数组中
		if(arr[l] < arr[r]){
			temp[tempIndex] = arr[l];
			l++;
			tempIndex++;
		}
		// 如果右边的值小,那么就将右边的值放入到临时数组中
		if(arr[r] < arr[l]){
			temp[tempIndex] = arr[r];
			r++;
			tempIndex++;
		}		
	}

	// 退出循环后,说明有一个数组中的值已经全部添加到临时数组中
	// 接下来将另外一个数组中的值添加到临时数组中
	while(l <= mid){
		temp[tempIndex] = arr[l];
		l++;
		tempIndex++;
	}
	while(r <= right){
		temp[tempIndex] = arr[r];
		r++;
		tempIndex++;
	}

	// 接下来就将临时数组中的值放入到原始数组中
	// 设置原始数组中的下标
	int leftIndex = left;
	// 将临时数组中的下标初始化
	tempIndex = 0;

	// 将临时数组中的值放到原始数组中
	while(leftIndex <= right){
		arr[leftIndex] = temp[tempIndex];
		leftIndex++;
		tempIndex++;
	}

}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值