<Java>排序算法


以升序为例——

1.选择排序

首先在待排序的序列中找到最小元素,存放在待排序序列的起始位置;然后,从剩下的待排序序列中继续寻找最小元素,放在已排序序列的末尾。以此类推,直到所有的元素排序完毕。

void SelectSort(int a[], int len)
{
	for(int i=0; i<len-1;i++)//i代表了已排序序列中的元素个数
	{
		for(int j=i+1; j<len;j++)//寻找待排序序列中最小元素的过程
		{
			if(a[i]>a[j]) a[i]<————>a[j];
		}
	}
}

2.冒泡排序

冒泡的含义——越大的元素会经由交换慢慢浮到数列末端。
重复地走访要排序的序列,一次比较相邻的两个元素,若大小与顺序不符就交换,每轮走访后都可以将当前前排最大的数提取出来。

void BubbleSort(int a[], int len)
{
	for(int i=0;i<len;i++)
	{
		for(int j=0;j<len-1-i;j++)
		{
			if(a[j]>a[j+1]) a[j]<————>a[j+1];//把较大的值往后推,第一轮结束后最后一个值是最大的。
		}
	}
}

3.插入排序

从数组的第2个值开始往前遍历,如果比前置位的值小,则自己必然要插入到前面已排序序列中的某一个位置?哪个位置?由于数组不能直接增减元素个数,故必须通过邻近比较、数组值挪位,来最终确定自己的插入位置。——每次遍历,遍历位置以前序列都是排好的。

void insertSort(int a[],int len)
{
	for(int i=1; i<len; i++)
	{
		if(a[i]<a[i-1])
		{
			int j; int temp = a[i];//由于数组通过覆盖来更新,故先记录下当前需要插入到前排的值
			for(j=i-1; j>=0 && a[j]>temp; j--)
			{
				a[j+1]=a[j];//寻找待插入的位置,如果不是,前面的值就依次挪位;如果是,则跳出循环
			}
			a[j+1]=temp;
		}
	}
}

4.快速排序

定义两个指针分别指向待排序序列的首尾,确定一个基准值(一般为待排序序列的第一个值),每一轮比较过后,基准值前面的数都比其小,后方的数都比其大。于是原序列被拆分成了两个小的待排序序列,以此递归,最终实现排序。

找到一个比较好理解的博文:https://blog.csdn.net/nrsc272420199/article/details/82587933
具体的过程如下:

public static void quickSort(int[] A, int low, int high)
{
	if(low<high)
	{
		int index = getIndex(A,low,high);

		quickSort(A,low,index-1);//递归查找
		quickSort(A,index+1,high);
	}

}
public static int getIndex(int[] A, int l, int h)
{
	int base = A[l];
	while(l<h)
	{
		while(l < h && A[h]>=base)//h指向的值往前挪,直到找到比基准数小的值。
		{
			h--;
		}
		A[l]=A[h];//比基准数小的值赋给l所指向的数组位置
		while(l < h && A[l]<=base)//l指向的值往后挪,直到找到比基准数大的值。
		{
			l++;
		}
		A[h]=A[l];//比基准数大的值赋给h所指向的数组位置
	}
	A[h] = base;
	return h;
}

5.希尔排序

也称缩小增量排序,是插入排序的改进,将数组分为若干个小数组进行插入排序,逐渐合并成原数组。

public static void shellSort(int[] A, int delta)
{
	int increasement = A.length;
	do
	{
		increasement = (increasement+1)/delta;//初始每个小序列的元素个数为delta,序列总数为increasement个
		for(int i=0; i<increasement; i++)//遍历每个小序列,一共increasement个
		{
			//下面是插入排序的操作,注意:每个小序列的第2个元素开始,往前遍历,增量不是1,是increasement
			for(int j=i+increasement; j<A.length ; j+=increasement)
			{       
				 if(A[j]<A[j-increasement])
				 {
					int k;
					int temp=A[j];
					for(k=j-increasement; k>=0 && A[k]>temp ;k-=increasement)
					{
						//循环移动覆盖数组值
						A[k+increasement]=A[k];
					}
					A[k+increasement]=temp;
				 }	
			}				
		}
	}
	while (increasement>1);
}

6.堆排序

利用二叉树的性质。
a.对数组进行二叉树排列,循环遍历每个非叶子节点,若发现子节点的数比自己大,则记录较大值位置max,然后交换两个数的位置,并对发生交换的子节点进行递归,以调整后续的节点相对位置。
b.每一轮遍历,都会把当前的最大值调整到栈顶,因此把栈顶元素与待排序序列的最后一个位置元素相交换。再把需要比较的节点总数减1,继续下一轮遍历。
c.遍历所有轮数结束后,即排序结束。

public static void heapAdjust(int[] Arr, int i ,int size)	//size是要比较的节点总数
{
    int max = i;
    int left = 2*i+1;
    int right = 2*i+2;
    if(left<size && Arr[left]>Arr[max])
        max = left;
    if(right<size && Arr[right]>Arr[max])
        max = right;
    if(max != i)
    {
        int temp;
        temp = Arr[max];
        Arr[max] = Arr[i];
        Arr[i] =temp;
        heapAdjust(Arr,max,size);
    }
}
public static void heapSort(int[] Arr, int size)
{
    for(int i=(size-1)/2; i>=0; i--)//循环完成一次,堆排序排完一次,都把最大值放在根节点位置上了
    {
        heapAdjust(Arr,i,size);
    }
    //把根节点上的那个最大值放到堆顶,对除堆顶外的剩余元素继续进行堆排序,要比较的节点总数是递减的size是要递减的
    if(size>0)
    {
        int temp;
        temp = Arr[0];
        Arr[0] = Arr[size-1];
        Arr[size-1] = temp;
        heapSort(Arr,--size);
    }
}

7.归并排序

——对整个待排序序列不断递归分解成两份,直至每份小序列只有1个数;
——从最小的序列开始,不断排序合并,每次合并后的这部分序列都是有序的。

public static void mergeSort(int[] Arr, int left, int right )
{
    if(left<right)
    {
        int mid = left+(right-left)/2;		//防止溢出
        mergeSort(Arr,left,mid);		//当l和r相差1时,此操作使得两者会相等,只剩一个数,无需再递归,开始合并。否则陷入死循环……
        mergeSort(Arr,mid+1,right);
        merge(Arr,left,mid,right);
    }
}
public static void merge(int[] Arr,int left, int mid, int right) //合并操作,针对两个有序序列(把一个序列看成两部分)(l,m)(m+1,r)
{
    int i = left;
    int j = mid+1;
    int k = 0;
    int[] temp = new int[right-left+1];
    while(i<=mid && j<=right)	//循环比较两个序列中的较小值,此循环直接完成min(m,n)个元素的合并
    {
        if(Arr[i]<Arr[j])
            temp[k++] = Arr[i++];
        else
            temp[k++] = Arr[j++];
    }

    while(j<=right)		//m<n
    {
        temp[k++] = Arr[j++];
    }
    while(i<=mid)		//m>n
    {
        temp[k++] = Arr[i++];
    }
    //把temp的值重新赋给Arr数组
    for(int p=0; p<temp.length; p++)
    {
        Arr[p+left] = temp[p];
    }
}

8.计数排序

public static int[] countingSort(int[] Arr)
{
    int len1= Arr.length;
    int max = getMax(Arr);
    int min = getMin(Arr);
    int len2 = max-min+1;
    int[] countArr = new int[len2];
    int[] result = new int[len1];
    int index;
    //第一次转变,负数变正数的同时,键值变索引,记录元素出现次数
    for(int i= 0; i<len1; i++)
    {
        countArr[Arr[i]-min]++;
    }
    //第二次转变,元素累计出现次数
    for(int i=1; i<len2; i++)
    {
        countArr[i] += countArr[i-1];
    }
    //根据Arr[i]的值,确定countArr[Arr[i]]的值A,再把countArr[A]的值存到result中,
    for(int i=len1-1; i>=0; i--)
    {
        index = countArr[Arr[i]-min];
        result[index-1] = Arr[i];
        countArr[Arr[i]-min]--;
    }
    return result;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值