排序【数据结构与算法Java】
- 排序
- 插入类排序
- 直接插入排序
- 折半插入排序
- 希尔排序
- 交换类排序
- 冒泡排序
- 快速排序
- 选择类排序
- 简单选择排序
- 树形选择排序
- 堆排序
- 归并类排序
- 二路归并排序
- 自然归并排序
- 分配类排序
- 多关键字排序
- 链式基数排序
- 外部排序
- 置换选择排序
- 多路归并外排序
排序
插入类排序
直接插入排序
折半插入排序
希尔排序
package sort1;
/**
* @author CSDN@日星月云
* @date 2022/10/30 21:29
*/
public class InsertSort1 {
public static void main(String[] args) {
int[]nums={-1,1,2,3,4,5,0,9,8,7,6};//0号不存储有效数字
//直接插入排序 稳定
// new InsertSort1().insertSort(nums);
//改进的直接插入排序 稳定
// new InsertSort1().insertSortPlus(nums);
//折半插入排序 稳定
// new InsertSort1().biInsertSort(nums);
//增量序列 不稳定
// new InsertSort1().shellSort(nums,new int[]{4,2,1});
new InsertSort1().shellSort(nums,new int[]{7,3,1});
for (int i = 1; i < nums.length; i++) {
System.out.print(nums[i]+"\t");
}
}
//直接插入排序
void insertSort(int[] nums){
for (int i = 2; i <nums.length ; i++) {
nums[0]=nums[i];//监视哨备份待查记录
int j;
for (j = i-1; nums[0]<nums[j]; j--) {
nums[j+1]=nums[j];//记录后移
}
nums[j+1]=nums[0];//插入正确位置
}
}
//待插记录已是当前有序的最大记录,不需要后移排序
//改进的直接插入排序
void insertSortPlus(int[] nums){
for (int i = 2; i <nums.length ; i++) {
if(nums[i]<nums[i-1]){//如果不小于,就是待插记录已是当前有序的最大记录
nums[0]=nums[i];//监视哨备份待查记录
int j;
for (j = i-1; nums[0]<nums[j]; j--) {
nums[j+1]=nums[j];//记录后移
}
nums[j+1]=nums[0];//插入正确位置
}
}
}
//折半插入排序
//因为插入到有序列中,有折半快速找到位置
void biInsertSort(int []nums){
for (int i = 2; i <nums.length ; i++) {
if(nums[i]<nums[i-1]){//如果不小于,就是待插记录已是当前有序的最大记录
nums[0]=nums[i];//监视哨备份待查记录
//折半查找nums[i]插入位置
int low=1;
int high=i-1;
while (low<high){
int mid=(low+high)/2;
if(nums[0]<nums[mid]){
high=mid-1;
}else{
low=mid+1;
}
}
for (int j = i-1; j>=low; j--) {
nums[j+1]=nums[j];//记录后移
}
nums[low]=nums[0];//插入正确位置
}
}
}
//希尔排序
//最小增量排序
void shellInsert(int[] nums,int dk){
for (int i = dk+1; i <nums.length ; i++) {
if(nums[i]<nums[i-1]){//如果不小于,就是待插记录已是当前有序的最大记录
nums[0]=nums[i];//监视哨备份待查记录
int j;
for (j = i-dk; j>0&&nums[0]<nums[j]; j-=dk) {
nums[j+dk]=nums[j];//记录后移
}
nums[j+dk]=nums[0];//插入正确位置
}
}
}
//dlta 增量序列
void shellSort(int[] nums,int dlta[]){
int t=dlta.length;//t为增量序列的长度
for (int k=0;k<t;k++){
shellInsert(nums,dlta[k]);
}
}
}
交换类排序
冒泡排序
package sort;
/**
* @author CSDN@日星月云
* @date 2022/10/30 22:06
*/
public class SwapSort {
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5, 0, 9, 8, 7, 6};//0号不存储有效数字
//冒泡排序
// new SwapSort1().bubbleSort(nums);
//改进冒泡排序
new SwapSort().bubbleSortPlus(nums);
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + "\t");
}
}
public void swap(int [] nums,int i,int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
//冒泡排序
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]){
swap(nums,j,j+1);
}
}
}
}
//改进冒泡排序
//如已排好序,直接跳出
public void bubbleSortPlus(int[] nums){
boolean flag=true;
for (int i = 0; i < nums.length&&flag; i++) {
flag=false;
for (int j = 0; j <nums.length-1-i ; j++) {
if(nums[j]>nums[j+1]){
swap(nums,j,j+1);
flag=true;
}
}
}
}
}
快速排序
package sort1;
/**
* @author CSDN@日星月云
* @date 2022/10/21 23:13
*/
public class QuickSort1 {
public static void main(String[] args) {
int[]nums={-1,1,2,3,4,5,0,9,8,7,6};//0号不存储有效数字
new QuickSort1().qkSort(nums,1, nums.length-1);
for (int i = 1; i < nums.length; i++) {
System.out.print(nums[i]+"\t");
}
}
void qkSort(int[]nums,int low,int high){
int pos;
if (low<high){
pos=qkPass(nums, low,high);
qkSort(nums, low,pos-1);
qkSort(nums, pos+1,high);
}
}
int qkPass(int[] nums,int low,int high){
nums[0]=nums[low];//枢轴
while(low<high){
while (low<high&&nums[high]>nums[0]) --high;
nums[low]=nums[high];
while (low<high&&nums[low]<nums[0]) ++low;
nums[high]=nums[low];
}
nums[low]=nums[0];
return low;
}
}
package sort;
/**
* @author CSDN@日星月云
* @date 2022/10/21 23:13
*/
public class QuickSort {
public static void main(String[] args) {
int[]nums={1,2,3,4,5,0,9,8,7,6};//0号存储有效数字
new QuickSort().qkSort(nums,0, nums.length-1);
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i]+"\t");
}
}
void qkSort(int[]nums,int low,int high){
int pos;
if (low<high){
pos=qkPass(nums, low,high);
qkSort(nums, low,pos-1);
qkSort(nums, pos+1,high);
}
}
int qkPass(int[] nums,int low,int high){
int tmp=nums[low];//枢轴
while(low<high){
while (low<high&&nums[high]>tmp) --high;
nums[low]=nums[high];
while (low<high&&nums[low]<tmp) ++low;
nums[high]=nums[low];
}
nums[low]=tmp;
return low;
}
}
选择类排序
简单选择排序
package sort;
/**
* @author CSDN@日星月云
* @date 2022/10/30 22:14
*/
public class SelectSort {
public static void main(String[] args) {
int[]nums={1,2,3,4,5,0,9,8,7,6};
//简单选择排序 不稳定
//树形选择排序
//堆排序 不稳定
new SelectSort().selectSort(nums);
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i]+"\t");
}
}
public void swap(int [] nums,int i,int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
//简单选择排序
void selectSort(int[] nums){
for (int i = 0; i < nums.length; i++) {
int k=i;
for (int j = i+1; j <nums.length ; j++) {
if (nums[j]<nums[k]){//k是擂台
k=j;
}
}
if (k!=i){
swap(nums,i,k);
}
}
}
}
树形选择排序
堆排序
package sort1;
import sort.InsertSort;
/**
* @author CSDN@日星月云
* @date 2022/10/30 23:04
*/
public class HeapSort1 {
public static void main(String[] args) {
int max=Integer.MAX_VALUE;
// //测试堆的筛选
// int[]nums={max,72,12,19,33,68,33,80,46};//0号不存储有效数字
// new HeapSort1().heapAdjust(nums,1, nums.length-1);
//测试建立初始堆
int[]nums={max,46,12,33,72,68,19,80,33};//0号不存储有效数字
// new HeapSort1().createHeap(nums);
//测试堆排序
new HeapSort1().heapSort(nums);
for (int i = 1; i < nums.length; i++) {
System.out.print(nums[i]+"\t");
}
//80 72 68 46 33 33 19 12
}
//堆的筛选
void heapAdjust(int[] nums,int s,int m){
//已知nums[s..m]中记录的关键字除nums[s]之外均满足堆的定义
//本函数调整nums[s]的关键字,是nums[s..m]成为一个小顶堆
int t=nums[s];
for (int j=2*s;j<=m;j*=2){
//沿key较小的孩子结点向下筛选
if (j<m&&nums[j]>nums[j+1]){
j++;//j为key较小的记录的下标
}
if(t<=nums[j]){
break;
}
//t应插入位置s
nums[s]=nums[j];
s=j;
}
nums[s]=t;
}
//建立初始堆
void createHeap(int [] nums){
int n=nums.length-1;//有效记录个数
for (int i=n/2;i>=1;i--){
heapAdjust(nums,i,n);
}
}
//堆排序
void heapSort(int [] nums){
int n=nums.length-1;//有效记录个数
createHeap(nums);
for (int i=n;i>=2;i--){
nums[0]=nums[1];
nums[1]=nums[i];
nums[i]=nums[0];
heapAdjust(nums,1,i-1);
}
}
}
归并类排序
二路归并排序
自然归并排序
package sort1;
/**
* @author CSDN@日星月云
* @date 2022/10/30 22:25
* 归并类排序
*/
public class MergeSort1 {
public static void main(String[] args) {
int[]nums={-1,1,2,3,4,5,0,9,8,7,6};//0号不存储有效数字
//二路归并排序
// int[] copy=new int[nums.length];
// for (int i=0;i<nums.length;i++){
// copy[i]=nums[i];
// }
// new MergeSort1().mergeSort(nums,copy,0,nums.length-1);
//自然归并排序
new MergeSort1().natureMergeSort(nums,nums.length);
for (int i = 1; i < nums.length; i++) {
System.out.print(nums[i]+"\t");
}
}
//二路归并排序
void mergeSort(int [] nums,int[] copy,int left,int right){
//对上下限值分别为left和right的记录序列L进行归并排序
//其中copy为同类型的记录,由于复制保存原记录序列
int middle;
if(left<right){
middle=(left+right)/2;//找中间位置进行划分
mergeSort(nums,copy,left,middle);//对左半部分进行递归归并排序
mergeSort(nums,copy,middle+1,right);//对右半部分进行递归归并排序
merge(nums,copy,left,right,middle);//进行归并
}
}
void merge(int[] nums,int[] copy,int left,int right,int middle){
int i,p1,p2;
for (i=left;i<=right;i++){//用copy记录临时保存待排序记录序列
copy[i]=nums[i];
}
p1=left;//左半部分有序记录的起始位置
p2=middle+1;//右半部分有序记录的起始位置
i=left;//左半部分开始进行归并
while(p1<=middle&&p2<=right){
//取两个有序半区中关键字较小的记录
if (copy[p1]<=copy[p2]){
nums[i]=copy[p1];//去较小的记录放到合并后的记录序列中
p1++;
} else{
nums[i]=copy[p2];
p2++;
}
i++;
}
//剩下的序列无论是左半部分还是右半部分都直接复制到合并后的记录序列中
while (p1<=middle){
nums[i]=copy[p1];
i++;
p1++;
}
while (p2<=middle){
nums[i]=copy[p2];
i++;
p2++;
}
}
//自然归并排序
//将两个有序的子序列nums[low..m]和nums[m+1..high]归并成一个有序的子序列nums[low..high]
void merge(int[]nums,int l,int m,int r){
int i=l,j=m+1,p=0,q;
int [] copy=new int[r-l+1];
while (i<=m&&j<=r){
//取两个有序半区中关键字较小的记录
if(nums[i]<=nums[j]){
copy[p++]=nums[i++];
}else {
copy[p++]=nums[j++];
}
}
//剩下的序列无论是左半部分还是右半部分都直接复制到合并后的记录序列中
if (i>m){
for (q = j; q <=r ; q++) {
copy[p++]=nums[q];
}
}else {
for (q=i;q<=m;q++){
copy[p++]=nums[q];
}
}
for (p=0,i=l;i<=r;p++,i++){
nums[i]=copy[p];//归并完成后将结果复制回R[low..high]
}
}
void natureMergeSort(int[] nums,int n){
int i,sum,low,mid,high;
while (true){
i=0;
sum=1;
while (i<n-1){
low=i;
while (i<n-1&&nums[i]<nums[i+1]){ i++; }
mid=i++;
while (i<n-1&&nums[i]<nums[i+1]){ i++; }
high=i++;
if (i<=n){
merge(nums,low,mid,high);
sum++;
}
}
if (sum==1) break;
}
}
}
分配类排序
多关键字排序
链式基数排序
外部排序
置换选择排序
多路归并外排序