目录
学习总结:
排序算法中,选择排序和冒泡排序比较简单,两次循环就可以求解;
1.选择排序
public class SelectSort {
public static void main(String[] args) {
int[] array = new int[]{4, 2, 6, 7, 3, 10, 4, 1, 9, 8};
selectSort(array);
System.out.println("选择排序:"+Arrays.toString(array));
}
//遍历所有的数,将当前遍历的数与后面的所有数进行比较,选择最小的数放在前面
public static void selectSort(int[] array){
for (int i = 0; i < array.length; i++){
int minIndex = i;
for(int j = i+1; j < array.length; j++){
if(array[minIndex] > array[j]){
minIndex = j;
}
}
if(minIndex != i){
int temp = array[i];
array[i] = array[minIndex];
array[minIndex] = temp;
}
}
}
}
2、冒泡排序
public class BubbleSort {
public static void main(String[] args) {
int[] array = new int[]{4,2,6,7,3,10,4,1,9,8};
bubbleSort(array);
System.out.println("冒泡排序:"+ Arrays.toString(array));
}
public static void bubbleSort(int[] array) {
for (int i = 0; i < array.length-1;i++){
for(int j = 0;j < array.length-1-i; j++){
if(array[j] > array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
}
}
3、快速排序
快速排序选择一个标准比较值,分别从左边和右边与标准值进行比较,第一次比较完之后,以比较值为分界线,左边比比较值小,右边比比较值大,根据这个结果,可以继续这种算法,即进行递归,再将两部分的数组继续分别拆分成两部分数组。
public class QuickSort {
public static void main(String[] args) {
int[] array = new int[]{4,2,6,7,3,10,4,1,9,8};
quickSort(array,0,array.length-1);
System.out.println("快速排序:"+Arrays.toString(array));
}
public static void quickSort(int[] array, int start, int end) {
if(start < end){//在方法中的左边的指针小于右边的指针时,才执行
int low = start;
int high = end;
int comp = array[low];
while (low < high) {//保证右边的指针不会跑到左边
while (low < high && array[high] >= comp) {
//在右边的元素比标准大时,指针左移,但是需要保证不会移到比左边指针更小的位置
high--;
}
array[low] = array[high];//在右边的元素比标准小时,值赋给左边的元素
//同理
while (low < high && array[low] <= comp) {
low++;
}
array[high] = array[low];
}
//low = high时,将标准值赋给此位置的元素
array[low] = comp;
//处理排序后的左半部分元素
quickSort(array, start, low - 1);
//处理排序后的右半部分元素
quickSort(array, low + 1, end);
}
}
}
4、归并排序
归并排序是对于两个有序的数组来说,可以以此比较两个数组中的值,选取较小的值填入结果数组,为了得到两个有序的数组,首先需要进行递归,将数组拆分为更小的数组,使他们有序。
快速排序:先排再递归
归并排序:先递归再排
public class MergeSort {
public static void main(String[] args) {
int[] array = new int[]{4,2,6,7,3,10,4,1,9,8};
mergeSort(array,0,array.length-1);
System.out.println("归并排序:"+Arrays.toString(array));
}
public static void mergeSort(int[] array,int start,int end){
if(start < end){
int[] temp = new int[end - start + 1];//创建一个数组,用于存放排序后的结构
int mid = (start + end)/2;//以mid为界限将数组分开
int left = start;//左边数组的其实位置
int right = mid+1;//右边数组的起始位置
int index = 0;//temp数组中的下标
//先递归,将数组分为两部分有序的数组,对其进行归并排序
//左半部分,继续划分
mergeSort(array,start,mid);
//右半部分划分
mergeSort(array,mid+1,end);
//比较两部分数组中的值,选取小的值
while (left <= mid && right <= end){
if(array[left] <= array[right]){
temp[index++] = array[left++];
}else {
temp[index++] = array[right++];
}
}
//将数组中多余的元素取出,放入temp
while (left <= mid){
temp[index++] = array[left++];
}
while (right <= end){
temp[index++] = array[right++];
}
//将排序后的数组赋给原数组
for(int i = 0;i < temp.length;i++){
array[i+start] = temp[i];
}
}
}
}
5、基数排序
将数组中所有的元素,从个位数开始,放入对应的桶中,然后从桶中按顺序取出,会得到对于小于2位数的元素来说有序的数组,然后再放入十位数字,取出后同样会得到对于小于3位数的元素来说的有序的数组。因此,放入数组中最大元素的所有位置的数字后,再取出,数组就变成有序的数组了。
public class RadixSort {
public static void main(String[] args) {
int[] array = new int[]{4,2,6,7,3,10,4,1,9,8};
radixSort(array);
System.out.println("基数排序:"+Arrays.toString(array));
}
public static void radixSort(int[] array){
//先求出数组中最大值有几位数,以确定外层循环的次数
int max = array[0];
for(int i = 1;i < array.length;i++){
if(array[i] > max){
max = array[i];
}
}
int maxLength = (max + "").length();//最大值的位数
int[][] temp = new int[10][array.length];//用来存放数组中放入到桶中的元素,每位数有10种取值情况
int[] count = new int[10];//计数,计算每位数的元素数量
//确定比较次数,依次取元素的个位、十位、百位数......
for(int i = 0,n = 1; i < maxLength;i++,n*=10){
//遍历元素取余,并放入temp中相应的位置
for (int j = 0;j < array.length; j++){
int num = array[j]/n%10;//取余数
temp[num][count[num]] = array[j];
count[num]++;//余数为num的数量计数加1
}
//将temp中的元素取出,赋给原数组
int index = 0;
for(int k = 0; k < count.length;k++){
if(count[k] != 0){
for(int l = 0;l < count[k]; l++) {
array[index] = temp[k][l];
index++;
}
count[k] = 0;
}
}
}
}
}
6、插入排序
插入排序原理是从第2个元素开始,拿出这个元素与前面的所有元素比较,找到比它小的位置插入,其他的位置全部向右移一位。
public class InsertSort {
public static void main(String[] args) {
int[] array = new int[]{4,2,6,7,3,10,4,1,9,8};
insertSort(array);
System.out.println("插入排序:"+Arrays.toString(array));
}
public static void insertSort(int[] array){
//原理是,遍历元素,将每个元素提出来,插入到正确的位置
for(int i = 1; i < array.length;i++){//从第1位开始遍历,认为第0位是有序的
int temp = array[i]; //记下需要比较的值
int j;
//遍历需要比较的值(temp)左边的所有元素
//用temp与左边的值进行比较,如果小于,即将数组的元素右移,直到找到第一个比temp小的元素
//将temp值赋给这个元素
for(j = i ; j > 0 && temp <= array[j-1]; j--){
array[j] = array[j-1];
}
array[j] = temp;
// for(j = i-1 ; j >= 0 && temp <= array[j]; j--){
// array[j+1] = array[j];
// }
// array[j+1] = temp;
}
}
}
7、希尔排序
希尔排序与插入排序类似,不过间隔不再是1,而是变换的间隔,一般第一次取数组长度的二分之一,之后继续除以2,知道间隔小于0,遍历所有的间隔值,其他的步骤与插入排序一样。希尔排序比插入排序更优的原因是,希尔排序会使数组相比数组来说更有序,遍历的次数比插入排序少。
public class ShellSort {
public static void main(String[] args) {
int[] array = new int[]{4,2,6,7,3,10,4,1,9,8};
shellSort(array);
System.out.println("希尔排序:"+Arrays.toString(array));
}
public static void shellSort(int[] array){
//与插入排序类似,不过间隔不是1,而是gap
//首先遍历gap的取值
for(int gap = array.length/2; gap > 0; gap /= 2){
//遍历元素,用插入排序的方法,注意是每隔gap取一个值
for(int i = gap; i < array.length; i++){
int j;
int temp = array[i];
for(j = i; j >= gap && temp < array[j-gap]; j -= gap){
array[j] = array[j-gap];
}
array[j] = temp;
}
}
}
}
8、堆排序
堆排序原理是,先将数组转换为大顶堆,然后将大顶堆中的第一个元素即最大的元素和最后一个元素交换,即最大的元素会在最后,然后最后一个元素不再参与排序,继续将数组转换成大顶堆,不过之后只需要将第一个元素重新转换就行了,然后同样将大顶堆的第一个元素和参与排序的最后一个元素位置进,循环上述操作。
public class HeapSort {
public static void main(String[] args) {
int[] array = new int[]{4,2,6,7,3,10,4,1,9,8};
heapSort(array);
System.out.println("堆排序:"+ Arrays.toString(array));
}
public static void heapSort(int[] array){
//开始位置是最后一个非叶子节点
int start = (array.length - 1)/2;
//调整为大顶堆
for(int i=start;i>=0;i--){
maxHeap(array,array.length,i);
}
//先把数组中的第0个和堆中的最后一个数交换位置,再把前面的处理为大顶堆。
for (int i = array.length-1;i>0;i--){
int temp = array[0];
array[0] = array[i];
array[i] = temp;
//只需将为位置0处重新转换为大顶堆,其它地方已经是大顶堆了
//并且不再包含交换的元素,其已经是需要排序的元素中最大的值了,不再参与排序
//因此size为i,即每次循环的时候减1,直至最后一个元素
maxHeap(array,i,0);
}
}
//将数组转换为大顶堆
public static void maxHeap(int[] array,int size,int index){
int leftNode = 2*index + 1;//左子节点
int rightNode = 2*index + 2;//右子节点
int max = index; //从当前节点index开始
//和两个子节点进行比较,找出最大的节点
if(leftNode < size && array[leftNode] > array[max]){
max = leftNode;
}
if(rightNode < size && array[rightNode] > array[max]){
max = rightNode;
}
//交换位置
if(max != index){
int temp = array[index];
array[index] = array[max];
array[max] = temp;
//交换位置后,可能会破坏之前排好的堆,因此重新调整之前排好的堆
maxHeap(array,size,max);
}
}
}