1.堆排序
public void heapify(int[] nums,int index,int size){
int left = index*2+1;
int right = index*2+2;
while(left<size){
//返回孩子中的最大值的下标
int largest = right<size && nums[right]>nums[left]? right:left;
largest = Math.max(nums[largest],nums[index])==nums[largest]? largest:index;//取当前节点和其所有孩子节点中较大的一个,返回下标largest
if(largest==index) break;//如果当前元素比孩子节点大,说明已经是大根堆
exchange(nums,largest,index);//如果不是,交换元素值
index = largest;
left = index*2+1;
}
}
public void heapInsert(int[] nums,int index){
while (nums[index]>nums[(index-1)/2]){
exchange(nums,index,(index-1)/2);
index = (index-1)/2;
}
}
public void heapSort(int[] nums){
if(nums.length==0||nums==null) return;
int heapSize = 0;
//将数组整体构建成一个大根堆
while (heapSize<nums.length){
heapInsert(nums,heapSize);
heapSize++;
}
exchange(nums,0,heapSize-1); //交换首位和末尾
heapSize--; //最大值在末尾,这个数找到了最终位置
// 每次构建一个大根堆,交换0位置和heapSize-1位置再次排成大根堆
while (heapSize>0){
heapify(nums,0,heapSize);
exchange(nums,0,heapSize-1);
heapSize--;
}
}
-
堆排序拓展
一个基本有序的数组,指的是每个元素排序过后的位置与原始位置相差不超过k,选择合适的方法对其进行排序。用堆排序时间复杂度为O(NlogK),当K的值相对N来说很小的话,logK几乎可以忽略,整个算法接近O(N)的时间复杂度,比较高效。*
public void sortArrDistanceLessK(int[] nums,int k){
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
int index = 0;
for (; index < k; index++) {
priorityQueue.add(nums[index]);
}
int i = 0;
for (; index < nums.length; i++,index++) {
nums[i] = priorityQueue.poll();
}
while(!priorityQueue.isEmpty()){
nums[i++] = priorityQueue.poll();
}
}
3.基数排序
public void radixSort(int[] nums){
if(nums==null||nums.length<2) return;
int maxbits = maxbits(nums);//数组中最大值有多少位
int[] help = new int[nums.length];//出桶辅助数组
for (int i = 1; i <= maxbits; i++) {//共进行maxbits轮入桶出桶操作
int[] count = new int[10];//某位记录<=i的数字有多少个
for (int j = 0; j < nums.length; j++) {//更新count数组
int bitNum = getbitNum(nums[j], i);
count[bitNum]++;
}
//将count数组转为前缀和数组,表示当前某位<=i的数字有多少个
for (int m = 1; m < count.length; m++) {
count[m] = count[m-1]+count[m];
}
for (int m = nums.length-1; m >=0; m--) {
int bitNum = getbitNum(nums[m], i);//当前元素该位数字
help[count[bitNum]-1] = nums[m];
count[bitNum]--;
}//出桶完成
//写入原数组
for (int m = 0; m < nums.length; m++) {
nums[m] = help[m];
}
}
}
// 求当前数组中最大值最多有多少位
public int maxbits(int[] nums){
int max = nums[0];
for (int i = 1; i < nums.length; i++) {
max = Math.max(nums[i],max );
}
int res = 0;
while(max!=0){
max/=10;
res++;
}
return res;
}
//求当前数字的个位/十位/百位.....
public int getbitNum(int num,int bit){
num = (num/((int) (Math.pow(10,bit-1)))%10);
return num;
}