冒泡排序
import java.util.Scanner;
/**
* 13 24 3 56 34 3 78 12 29 49 84 51 9 100
*/
public class Main {
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int N=sc.nextInt();
int[] nums=new int[N];
for(int j=0;j<N;j++){
nums[j]=sc.nextInt();
}
bubbleSort(nums);
for(int j=0;j<N;j++){
System.out.print(nums[j]+" ");
}
}
/**
*
* @param arrays
*/
public static void bubbleSort(int[] arrays){
for(int i=0;i<arrays.length-1;i++){
boolean flag=true;
for(int j=0;j<arrays.length-1-i;j++){
if(arrays[j]>arrays[j+1]){
swap(arrays,j,j+1);
flag=false;
}
}
if (flag) break;
}
}
public static void swap(int[] array,int i,int j){
int temp=array[i];
array[i]=array[j];
array[j]=temp;
}
}
按照另一个数组排序(冒泡排序变形)
按照数值个数排序
Description
对给定数组中的元素按照元素出现的次数排序,出现次数多的排在前面,如果出现次数相同,则按照数值大小排序。例如,给定数组为{2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12},则排序后结果为{3, 3, 3, 3, 2, 2, 2, 12, 12, 4, 5}。
Input
输入的第一行为用例个数;后面每一个用例使用两行表示,第一行为数组长度,第二行为数组内容,数组元素间使用空格隔开。
Output
每一个用例的排序结果在一行中输出,元素之间使用空格隔开。
Sample Input 1
1
4
2 3 2 5
Sample Output 1
2 2 3 5
public class Main {
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int T=sc.nextInt();
for(int t=0;t<T;t++){
int N=sc.nextInt();
int arr[]=new int[N];
for(int i=0;i<N;i++){
arr[i]=sc.nextInt();
}
Map<Integer,Integer> map=sortByTime(arr,N);
for(Map.Entry<Integer,Integer> entry:map.entrySet()){
int mapKey = entry.getKey();
int mapValue = entry.getValue();
//打印
for(int j=0;j<mapValue;j++){
System.out.print(mapKey+" ");
}
}
System.out.println("");
}
}
/**
* 按照数字出现的次数进行排序
* @param arr
*/
private static Map<Integer,Integer> sortByTime(int[] arr,int n) {
// Arrays.sort(arr);
Map<Integer,Integer> map=new TreeMap<>();
for(int i=0;i<n;i++){
map.put(arr[i],map.getOrDefault(arr[i],0)+1);
}
Set<Integer> keySet=map.keySet();
map.entrySet().stream().sorted(Map.Entry.comparingByValue());
return map;
}
}
插入排序
publi
c class Main {
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int T=Integer.parseInt(sc.nextLine());
for(int t=0;t<T;t++){
String[] numStr=sc.nextLine().trim().split(" ");
int nums[]=new int[numStr.length-1];
int N=Integer.parseInt(numStr[0]);
for(int i=0;i<nums.length;i++){
nums[i]=Integer.parseInt(numStr[i+1]);
}
sort(nums);
for(int i=0;i<N;i++){
System.out.print(nums[i]);
if(i!=nums.length-1) System.out.print(" ");
}
System.out.println("");
}
}
/**
* 插入排序
* @param nums
*/
static void sort(int[] nums){
for(int i=1;i<nums.length;i++){
int temp=nums[i];
int j;
for(j=i;j>0&&nums[j-1]>temp;j--){
nums[j]=nums[j-1];
}
nums[j]=temp;
}
}
}
希尔排序
shell排序,按照给定的间隔变化,打印排序结果。
知识点:
两种插入排序
1)简单插入排序:(稳定排序)
直接插入排序的排序思路是:每次将一个待排序的元素与已排序的元素进行逐一比较,直到找到合适的位置按大小插入。
2)希尔排序
按照步长进行分组,每组内进行希尔排序。
import java.util.Scanner;
/**
* shell排序,按照给定的间隔变化,打印排序结果。
* 第一行:用例个数T
* 第二行 :数组
* 第三行 :指定间隔,每个间隔用空格隔开
*
* Sample Input 1
* 1
* 49 38 65 97 76 13 27 49 55 4
* 5 3
*
* Sample Output 1
* 13 4 49 38 27 49 55 65 97 76
*/
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int T = Integer.parseInt(sc.nextLine().trim());
for (int t = 0; t < T; t++) {
String[] s = sc.nextLine().trim().split(" ");
int[] arr = new int[s.length];//保存数组
for (int i = 0; i < s.length; i++) {
arr[i] = Integer.parseInt(s[i]);
}
String[] s1 = sc.nextLine().trim().split(" ");
int path[] = new int[s1.length];//保存步数
for (int i = 0; i < path.length; i++) {
path[i] = Integer.parseInt(s1[i]);
}
shellOrder(arr, path);
//打印
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println("");
}
sc.close();
}
private static void shellOrder(int[] arr, int[] path) {
for (int i = 0; i < path.length; i++) {
orderByPath(arr, path[i]);
}
}
/**
* 根据步长进行排序
*
* @param array
* @param h
*/
private static void orderByPath(int[] array, int h) {
for (int i = h; i < array.length; i++) {
for (int k = i; k < array.length; k += h) {
//判断是否需要重新排序,如果小于k-h处的值,需要重新排序
if (array[k] < array[k - h]) {
int tempValue = array[k];
int j = k;
for (; j >= i && tempValue < array[j - h]; j -= h) {
array[j] = array[j - h];
}
array[j] = tempValue;
}
}
}
}
}
计数排序
Description
实现计数排序,通过多次遍历数组,统计比每一个元素小的其它元素个数,根据该统计量对数据进行排序。
Input
输入的每一行表示一个元素为正整数的数组,所有值用空格隔开,第一个值为数值长度,其余为数组元素值。
Output
输出的每一行为排序结果,用空格隔开,末尾不要空格。
分析:此题的重点是统计比每个元素小的其他元素的个数。
import java.util.Scanner;
public class Main {
public static void bsort(int array[])
{
int counts[]=new int[array.length];
int newarray[]=new int[array.length];
for(int i=0;i<array.length-1;i++)
for(int j=i+1;j<array.length;j++)
if(array[i]>=array[j])
counts[i]++;//计算小于等于array[i]的个数 加不加等号不影响结果
else
counts[j]++;//计算大于array[j]的个数
for(int i=0;i<array.length;i++)
newarray[counts[i]]=array[i];//根据位置存放元素
for(int i=0;i<newarray.length;i++)//按照题意输出结果
if(i!=newarray.length-1)
System.out.print(newarray[i]+" ");
else
System.out.println(newarray[i]);
}
public static void main(String args[])
{
Scanner in=new Scanner(System.in);
String arr[]=in.nextLine().split(" ");//按照题意输入,注意第一个是元素个数
int array[]=new int[arr.length-1];//保存要排序的数据
for(int i=1;i<arr.length;i++)
array[i-1]=Integer.parseInt(arr[i]);//将数据转换
bsort(array);
}
}
非递归归并排序
public class Main {
static Scanner scanner=new Scanner(System.in);
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int N=sc.nextInt();
int[] nums=new int[N];
for(int j=0;j<N;j++){
nums[j]=sc.nextInt();
}
mergeSort(nums);
for(int j=0;j<N;j++){
System.out.print(nums[j]+" ");
}
}
/**
* 非递归归并排序
* @param nums
*/
private static void mergeSort(int[] nums) {
//建立步长path
int path=1;
int n=nums.length;
while(path<=n){
//确定排序边界
for(int i=0;i<n-path;i=i+path+path){
int mid=Math.min(i+path-1,n-1);
int right=Math.min(i+path*2-1,n-1);
merge(nums,i,mid,right);
}
path=path*2;
}
}
/**
* 将子数组left到mid 以及 子数组 mid+1 right 进行合并
* @param nums
* @param left
* @param mid
* @param right
*/
static void merge(int nums[],int left,int mid,int right){
//建立辅助数组
int length=right-left+1;
int[] auxiliaryArray=new int[length];
int i=left;
int j=mid+1;
int index=0;
while(i<=mid&&j<=right){
if(nums[i]<=nums[j]){
auxiliaryArray[index++]=nums[i++];
}else{
auxiliaryArray[index++]=nums[j++];
}
}
while(i<=mid){
auxiliaryArray[index++]=nums[i++];
i++;
}
while (j<=right) {
auxiliaryArray[index++] = nums[j++];
}
//将辅助数组的结果填到原数组中
for(int t=0;t<auxiliaryArray.length;t++){
nums[left+t]=auxiliaryArray[t];
}
}
}
合并数组——n路归并——借助优先队列
import java.util.Scanner;
import java.util.PriorityQueue;
import java.util.Comparator;
/**
* 描述:给定k个已经排好序的数组。arr[k][k]
* 合并k个数组,并排好序。
* 输入 :第一行 T
* 第二行 N 数组数量
* 第三行 数组
* 思路:使用堆。
*/
public class Main {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int T=sc.nextInt();
for(int i=0;i<T;i++){
int N=sc.nextInt();
int [][]arr=new int[N][N];
for(int j=0;j<N;j++) {
for (int k = 0; k < N; k++){
arr[j][k] = sc.nextInt();
}
}
int[] res = mergeKArrays(arr, N);
//打印
for(int j=0;j<res.length;j++){
System.out.print(res[j]+" ");
}
System.out.println("");
}
sc.close();
}
static class Element{
int row,col,val;
public Element(int row, int col, int val) {
this.row = row;
this.col = col;
this.val = val;
}
}
public static int[] mergeKArrays(int[][] arr, int k){
PriorityQueue<Element> queue=new PriorityQueue<>(k, new Comparator<Element>() {
@Override
public int compare(Element o1, Element o2) {
return o1.val-o2.val;
}
});//默认小顶堆
int[] res=new int[k*k];
int index=0;
//初始化
for(int j=0;j<k;j++){
queue.offer(new Element(j,0,arr[j][0]));
}
while(!queue.isEmpty()){
//出队列
Element e=queue.poll();
res[index++]=e.val;
if(e.col+1<k) queue.offer(new Element(e.row,e.col+1,arr[e.row][e.col+1]));
}
return res;
}
}
倒置对的个数——归并排序应用
import java.util.Scanner;
/**
* Description
* 有一个由N个实数构成的数组,如果一对元素A[i]和A[j]是倒序的,即i<j但是A[i]>A[j]则称它们是一个倒置,
* 设计一个计算该数组中所有倒置数量的算法。要求算法复杂度为O(nlogn)
*
* Input
* 输入有多行,第一行整数T表示为测试用例个数,后面是T个测试用例,每一个用例包括两行,第一行的一个整数是元素个数,第二行为用空格隔开的数组值。
*
*
* Output
* 输出每一个用例的倒置个数,一行表示一个用例。
*
* Sample Input 1
* 1
* 8
* 8 3 2 9 7 1 5 4
*
* Sample Output 1
* 17
* 思路:采用归并排序
*
*/
public class Main {
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int T=sc.nextInt();
for(int i=0;i<T;i++){
int N=sc.nextInt();
int a[]=new int[N];
for(int j=0;j<N;j++) a[j]=sc.nextInt();
System.out.println(mergeSort(a,0,a.length-1));
}
}
public static int mergeSort(int[] array,int start,int end){
if(start>=end) return 0;
int mid=(start+end)/2;
return mergeSort(array,start,mid)+mergeSort(array, mid+1, end)+merge(array,start,end,mid);
}
public static int merge(int[] array,int left,int right,int mid){
//合并
int total=0;
int i=left;//左
int j=mid+1;//右侧
int newArray[]=new int[right-left+1];
int index=0;
while(i<=mid&&j<=right){
if(array[i]<=array[j]){
newArray[index++]=array[i++];
}else{
newArray[index++]=array[j++];
//则i比j要大,则i后面都比j大
total+=mid-i+1;
}
}
while(i<=mid){
newArray[index++]=array[i++];
}
while (j<=right){
newArray[index++]=array[j++];
}
//写回
for(int k=0;k<right-left+1;k++){
array[k+left]=newArray[k];
}
return total;
}
}
非递归快排
import java.util.Scanner;
import java.util.Stack;
/**
* Input
* 输入的每一行表示一个元素为正整数的数组,所有值用空格隔开,第一个值为数值长度,其余为数组元素值。
* Output
* 输出的每一行为排序结果,用空格隔开,末尾不要空格。
*
*
* Sample Input 1
* 13 24 3 56 34 3 78 12 29 49 84 51 9 100
* Sample Output 1
* 3 3 9 12 24 29 34 49 51 56 78 84 100
*/
public class Main {
static Scanner scanner=new Scanner(System.in);
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int N=sc.nextInt();
int[] nums=new int[N];
for(int j=0;j<N;j++){
nums[j]=sc.nextInt();
}
quickSort(nums);
for(int j=0;j<N;j++){
System.out.print(nums[j]+" ");
}
}
/**
* 非递归快速排序
* @param nums
*/
private static void quickSort(int[] nums) {
int low=0;
int high=nums.length-1;
int pivot;
if (low >= high)
return;
Stack<Integer> stack = new Stack<Integer>();
stack.push(low);
stack.push(high);
while (!stack.empty()) {
// 先弹出high,再弹出low
high = stack.pop();
low = stack.pop();
pivot = partion(nums, low, high);
// 先压low,再压high
if (low < pivot - 1) {
stack.push(low);
stack.push(pivot - 1);
}
if (pivot + 1 < high) {
stack.push(pivot + 1);
stack.push(high);
}
}
}
/**
* 根据分界点移动元素,并返回新的分界点
* @return
*/
static int partion(int[] array,int low,int high){//合并排序部分
int tmp = array[low];
while(low<high){
while(low < high && array[high] >= tmp){
--high;
}
if(low >= high){
break;
}else{
array[low]= array[high];//交换小值去前面
}
while(low < high && array[low] <= tmp){
++low;
}
if(low >= high){
break;
}else{
array[high] = array[low];//交换大值去后面
}
}
array[low] = tmp;//枢值归位
return low;
}
}
递归快排
private static void quickSort(int[] nums) {
int low=0;
int high=nums.length-1;
quick(nums,low,high);
}
private static void quick(int nums[],int low,int high){
if(low>=high) return;
int pivot=partion(nums,low,high);
quick(nums,low,pivot-1);
quick(nums,pivot+1,high);
}
按照数值个数排序
按照数值个数排序
Description
对给定数组中的元素按照元素出现的次数排序,出现次数多的排在前面,如果出现次数相同,则按照数值大小排序。例如,给定数组为{2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12},则排序后结果为{3, 3, 3, 3, 2, 2, 2, 12, 12, 4, 5}。
Input
输入的第一行为用例个数;后面每一个用例使用两行表示,第一行为数组长度,第二行为数组内容,数组元素间使用空格隔开。
Output
每一个用例的排序结果在一行中输出,元素之间使用空格隔开。
Sample Input 1
1
4
2 3 2 5
Sample Output 1
2 2 3 5
public class Main {
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int T=sc.nextInt();
for(int t=0;t<T;t++){
int N=sc.nextInt();
int arr[]=new int[N];
for(int i=0;i<N;i++){
arr[i]=sc.nextInt();
}
Map<Integer,Integer> map=sortByTime(arr,N);
for(Map.Entry<Integer,Integer> entry:map.entrySet()){
int mapKey = entry.getKey();
int mapValue = entry.getValue();
//打印
for(int j=0;j<mapValue;j++){
System.out.print(mapKey+" ");
}
}
System.out.println("");
}
}
/**
* 按照数字出现的次数进行排序
* @param arr
*/
private static Map<Integer,Integer> sortByTime(int[] arr,int n) {
// Arrays.sort(arr);
Map<Integer,Integer> map=new TreeMap<>();
for(int i=0;i<n;i++){
map.put(arr[i],map.getOrDefault(arr[i],0)+1);
}
Set<Integer> keySet=map.keySet();
map.entrySet().stream().sorted(Map.Entry.comparingByValue());
return map;
}
}