package sort;
/**
* @author Administrator
* @version 创建时间:2018年4月12日 上午9:32:48
* @ClassName 类名称
* @Description 类描述
*/
public class Sort {
private int[] nums= {2,4,6,7,98,0,2,6,9,1};
//private int[] nums= {5,4,3,2,1};
public void swap(int[] nums,int i,int j){//交换数组等集合里的元素,引用传递,而非值传递
int temp;
temp =nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
public void BubbleSort0(int[] nums,int n){//冒泡排序初级版:最最简单的交换排序
int i,j;
for(i=0;i<n-1;i++){
for(j=i+1;j<n;j++){
if(nums[i]>nums[j])
swap(nums,i,j);
}
}
}
public void BubbleSort(int[] nums,int n){//冒泡排序
int i,j;
for(i=0;i<n;i++){//每一轮比较把最小的放最前面
for(j=n-1;j>i;j--){//从最后到i两两交换,较小者放在前面,即“冒泡”,注意j是从后往前循环
if(nums[j-1]>nums[j])
swap(nums,j-1,j);
}
}
}
/*冒泡排序优化,增加标记来减少排序次数,避免因已经有序的情况下的无意义循环判断。*/
public void BubbleSort2(int[] nums,int n){
int i,j,flag=1;//flag用于标记是否有交换操作
for(i=0;i<n && flag==1;i++){//若flag为0,表示没有发生交换,则退出循环
flag = 0;//0表示没有交换
for(j=n-1;j>i;j--){
if(nums[j-1]>nums[j]){
swap(nums,j-1,j);
flag = 1;//若产生交换,flag置为1
}
}
}
}
//选择排序:寻找序列中的最小值,用当前位置的值交换最小值
public void SelectSort(int[] nums,int n){
int i,j,min;
for(i=0;i<n-1;i++){
min=i; //将当前下标定义为最小值下标
for(j=i+1;j<n;j++){ //循环之后的数据
if(nums[j]<nums[min]){//如果有小于当前最小值的关键字,将此关键字的下标赋值给min
min=j;
}
if(i!=min) //若min不等于i,说明找到最小值,交换
swap(nums,i,min);
}
}
}
/* 插入排序
* 基本思想是在遍历数组的过程中,假设在序号 i (i>=1)之前的元素即 [0..i-1] 都已经排好序,
* 本趟需要找到 i 对应的元素 x 的正确位置 k ,并且在寻找这个位置 k 的过程中逐个将比较过的元素往后移一位,
* 为元素 x “腾位置”,最后将 k 对应的元素值赋为 x
*/
public void InsertSort(int[] nums,int n){
int i,j,temp;
for(i=1;i<n;i++){
//只有当前位置i元素小于已经有序的[0,i-1]中的最大元素nums[i-1]时,才需要进行插入
if(nums[i]<nums[i-1]){
temp=nums[i];//存当前位置i的元素,其中[0,i-1]已经有序
for(j=i;j>0&&nums[j-1]>temp;j--){
nums[j]=nums[j-1];//从i-1开始遍历到0,比temp大的数后移一位
}
nums[j]=temp;//插入到合适的位置
}
}
}
/* 希尔排序
*/
public void ShellSort(int[] nums,int n){
int i,j,temp;
int h = 1; /* 关于步长,取值没有统一标准,必须小于size,最后一次步长要为1 */
for(h = 1;h < n/3;h= 3*h+1);//计算首次步长
for(;h>0;h=h/3){
for(i=h;i<n;i++){
//只有当前位置i元素小于已经有序的[0,i-1]中的最大元素nums[i-h]时,才需要进行插入
if(nums[i]<nums[i-h]){
temp=nums[i];//存当前位置i的元素,其中[0,i-1]已经有序
for(j=i;j>h-1&&nums[j-h]>temp;j=j-h){
nums[j]=nums[j-h];//从i-h开始遍历到h-1,比temp大的数后移h位
}
nums[j]=temp;//插入到合适的位置
}
}
}
}
/* 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上),
* 即[s..m]中记录的关键字除[s]之外均满足堆的定义 ;
* s表示所要调整的范围的开始下标,m表示结束的下标,
* 即[s,...,m],总个数为m-s+1,m可以取到
*/
private void HeapAdjust(int[] nums,int s,int m){
int i,temp;
temp = nums[s];//先取出当前元素s
for(i=2*s+1;i<=m;i=i*2+1){//从s结点的左子结点开始,也就是2s+1处开始,沿关键字较大的孩子结点向下筛选
if(i<m && nums[i]<nums[i+1]){//i为孩子节点中关键字较大的记录的下标;i<m保证右孩子存在
i++;
}
if(temp<nums[i]){
//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
nums[s]=nums[i];
s=i;
}else
break;
}
nums[s]=temp;//将当前元素插入到最终的位置
}
//堆排序
public void HeapSort(int[] nums,int n){
int i;
//1、构建大顶堆
for(i=n/2-1;i>=0;i--){
//从第一个非叶结点从下至上,从右至左调整结构
HeapAdjust(nums,i,n-1);//长度为n,则最后一个元素下标为n-1
}
//2.调整堆结构+交换堆顶元素与末尾元素
for(i=n-1;i>=0;i--){
swap(nums,0,i);//将堆顶元素与末尾元素进行交换
HeapAdjust(nums,0,i-1);//重新对堆进行调整
}
}
//归并排序
public void MergeSort(int[] nums,int n){
int[] temp = new int[n];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
MSort(nums,temp,0,n-1);
}
private void MSort(int[] nums,int[] temp,int left,int right){
int mid;
//if(left==right) temp[left]=nums[right];
if(left<right){
mid = (left+right)/2;
MSort(nums,temp,left,mid);//左边归并排序,使得左子序列有序
MSort(nums,temp,mid+1,right);//右边归并排序,使得右子序列有序
Merge(nums,temp,left,mid,right);//将两个有序子数组合并操作
}
}
//right为序列最后一位元素下标
private void Merge(int[] nums,int[] temp,int left,int mid,int right){
int i=left; //左序列指针
int j=mid+1; //右序列指针
int k=0; //临时数组指针
while(i<=mid && j<=right){
if(nums[i]<nums[j]){
temp[k++]=nums[i++];
}else{
temp[k++]=nums[j++];
}
}
while(i<=mid){ //将左边剩余元素填充进temp中
temp[k++]=nums[i++];
}
while(j<=right){ //将右序列剩余元素填充进temp中
temp[k++]=nums[j++];
}
k = 0;
while(left<=right){ //将temp中的元素全部拷贝到原数组中
nums[left++]=temp[k++];
}
}
//快速排序
public void QuickSort(int[] nums,int n){
QSort(nums,0,n-1);
}
public void QSort(int[] nums,int low,int high){
int pivot;
if(low<high){
pivot=Partition(nums,low,high);/*将L->r[low..high]一分为二,*/
/*算出枢轴值pivot */
QSort(nums,low,pivot-1);
QSort(nums,pivot+1,high);
}
}
public int Partition(int[] nums,int low,int high){
int pivotkey=nums[low];
while(low<high){
while(low<high && nums[high]>=pivotkey){
high--;
}
swap(nums,low,high);
while(low<high && nums[low]<=pivotkey){
low++;
}
swap(nums,low,high);
}
return low;
}
//二叉排序树
class Node{//二叉排序树的结点类
public int data;
public Node left;
public Node right;
public Node(int data){
this.data = data;
this.left = null;
this.right = null;
}
}
private Node root=null;
static int ii =0;//指针,将递归中序遍历的有序树放入nums数组中
public void BSTSort(int[] nums,int n){
CreateBST(nums,n);//根据待排序数组生成二叉排序树
MidOrderTraverse(root,nums);
}
public void InsertNode(int data){
Node newNode = new Node(data);
if(root == null){
root = newNode;
}else{
Node current = root;
Node parent = current;
while(current != null){
parent = current;
if(data < current.data){
current = current.left;
}else{
current = current.right;
}
}
if(data < parent.data){
parent.left = newNode;
}else{
parent.right = newNode;
}
}
}
public void CreateBST(int[] nums,int n){
for(int i = 0;i<n;i++){
InsertNode(nums[i]);
}
}
//二叉树中序遍历
public void MidOrderTraverse(Node root,int[] nums){
if(root != null){
MidOrderTraverse(root.left,nums);
nums[ii++]=root.data;
MidOrderTraverse(root.right,nums);
}
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
Sort ss = new Sort();
ss.BSTSort(ss.nums, ss.nums.length);
for(int i = 0;i<ss.nums.length;i++)
System.out.println(ss.nums[i]);
}
}
各种排序的Java实现
最新推荐文章于 2022-11-15 12:03:32 发布