假设数组的大小为n,数组为整数数组。
1.选择排序
每次排序从下标i开始,然后逐个比较i+1到n的元素,保证i位置上的元素是[i,n-1]中最小的(倒序为最大)。
在进行比较过程中,根据排序的标准,如果为正序,则将较小的保留在前面,较大的保留在后面。
public void ChooseSort(int[] nums){
for(int i = 0;i<nums.length;i++){
for(int j = i+1;j<n;j++){
if(nums[i]>nums[j]){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}
}
2.冒泡排序
两两依次比较,较大的放在后面。 每一轮比较之后,最后一位就是最大的值,从而使得下一轮可以少比较一位数字。
public void bubbleSort(int[] nums){
for(int i = 0;i<nums.length;i++){
for(int j = 0;j<nums.length-1-i;j++){
if(nums[j]>nums[j+1]){
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
}
其实冒泡和选择排序很像,只是选择排序对比的过程中前一个数始终是不变的,也就是要确定的目前最小值的下标,逐步将最小值换到当前位置。而冒泡排序是确定最大值,不断地两两向后对比,将较大值换到后面,然后最终确认当前范围的最大值。
3.快速排序
以数组的第一个数为基数,从后往前找,比它小的数,覆盖基数的位置。再从前往后找比它大的数,再覆盖到刚才比他小的数的位置。逐次寻找直到前后位置重合,此时这个位置就基数最后应该放入的位置,它对应于上一次比基数大的位置或者比基数小的位置。
public void quickSort(int[] nums,int start,int end){
if(start<end){
int low = start;
int high = end;
int std = nums[low];
while(low<high){
while(low<high&&nums[high]>=std){
high--;
}
//用右边的数替换左边的数
nums[low] = nums[high];
while(low<high&&nums[low]<=std){
low++;
}
//用左边的数代替右边的数
nums[high] = nums[low];
}
//此时 low=high,将std填入
nums[low] = std;
//处理标准数左边的数组
quickSort(nums,start,low-1);
//处理标准数右边的数组
quickSort(nums,low+1,end);
}
}
4.插入排序
认为前n个数是有序的,当插入第n+1个数的时候,从右往左依次对比,若小于则和前一个数进行互换,类似于冒泡。
public void insertSort(int[] nums){
for(int i = 0;i<nums.length;i++){
for(int j = i;j>0;j--){
if(nums[j]<nums[j-1]){
int temp = nums[j];
nums[j] = nums[j-1];
nums[j-1] = temp;
}
}
}
}
5.希尔排序
基于插入排序的思想,首先将数组按步长分成不同的部分,然后每个部分进行插入排序
public void shellSort(int[] nums){
for(int d = nums.length/2;d>0;d/=2){
for(int i = 0;i<d;i++){
//这一部分是插入排序
for(int j = i;j<nums.length;j+=d){
for(int k = j;k>i;k-=d){
if(nums[k]<nums[k-d]){
int temp = nums[k];
nums[k] = nums[k-d];
nums[k-d] = temp;
}
}
}
}
}
}
6.归并排序
将数组分成两个部分,然后依次递归,直到变成一个数字为止。而对于一个数字来说,他是有序的,再反向不断归并,成为一个有序的数组。
//1.首先假设已经把数组分成了两个有序部分,并对有序的部分进行合并
public void merge(int[] nums, int low,int mid,int high){
//用i,j两个变量分别来索引前半部分和后半部分的有序数字集合
int i = low;
int j = mid+1;
//用于存储归并后的有序的临时数组
int[] temp = new int[high-low+1];
int index = 0;
while(i<=mid&&j<=high){
if(nums[i]<nums[j]){
temp[index] = nums[i];
i++;
}else{
temp[index] = nums[j];
j++;
}
index ++;
}
while(i<=mid){
temp[index]=nums[i];
i++;
index++;
}
while(j<=high){
temp[index]=nums[j];
j++;
index++;
}
//最后把临时数组填入原数组的对应位置
for(int k=0;k<high-low+1;k++){
nums[low+k] = temp[k];
}
}
//2.然后写递归部分
public void mergeSort(int[] nums, int low, int high){
int mid = (low+high)/2;
if(low<high){
//先不断二分
mergeSort(nums,low,mid);
mergeSort(nums,mid+1,high);
//再自底向上不断归并
merge(nums,low,mid,high);
}
}
7.基数排序
基数排序就是从数字的每一位出发,先按当前位进行总体上的排序,然后不断将位数提高,修正排序结果
public void radixSort(int[] nums){
int n = nums.length;
//找到所有数字中的最大值,最大值具有的位数是最长的
int max = Integer.MIN_VALE;
for(int i = 0;i<n;i++){
max = Math.max(max,nums[i]);
}
int max_length = (max+"").length();
//建立用来存储当前位数字是i的temp[i][n]数组
int[][] temp = new int[10][n];
//建立计算当前位是i的数字有多少个的数组
int[][] temp_count = new int[10];
//对每一位循环进行排序
for(int i = 0;i<max_length;i++){
for(int j = 0;j<n;j++){
int num = nums[j];
//计算所有数组元素当前位的数字
int y = (num/Math.pow(10,i))%10;
temp[y][temp_count[y]] = num;
temp_count[y]++;
}
//依次从最低位到最高位填入原数组
int index = 0;
for(int k = 0;k<10;k++){
if(temp_count[k]!=0){
for(int l = 0;l<temp_count[k];l++){
nums[index] = temp[k][l];
index++;
}
}
temp_count[k] = 0;
}
}
}
8.堆排序
//1.首先要实现最大堆,将数组形成最大堆
public void maxheap(int[] nums, int size, int index){
//左子节点和右子节点
int left = 2*index+1;
int right = 2*index+2;
//找到两个节点中的最大值
int max = index;
if(left<size&&nums[left]>nums[max]){
max = left;
}
if(right<size&&nums[right]>nums[max]){
max = right;
}
//交换位置
if(max!=index){
int temp = nums[max];
nums[max] = nums[index];
nums[index] = temp;
//交换位置后继续后面的堆
maxheap(nums,size,max);
}
}
//2.大顶堆实现从小到大排序
public void heapSort(int[] nums){
int n = nums.length;
//首先建立原数组的大顶堆
//开始位置是最后一个非叶子节点,也是最后一个节点的父节点
int start = (n-1)/2;
for(int i = start;i>=0;i--){
maxheap(nums,n,i);
}
//此时数组已经变成了大顶堆,即父节点要大于子节点
for(int i = n-1;i>=0;i++){
//接下来,每次将堆顶的元素换到后面第i个位置,然后再对前0~i-1的位置进行最大堆调整
int temp = nums[0];
nums[0] = nums[i];
nums[i] = temp;
//对前0~i-1的位置进行最大堆调整
//除了堆顶根节点以及其左右子树不是大顶堆,其他都是,所以从堆顶开始调整
maxheap(nums,i,0);
}
}