package com.tx;
public class Sort {
/**
* 冒泡排序
* 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
* 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
* 针对所有的元素重复以上的步骤,除了最后一个。
* 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
* 时间复杂度:最好:O(n^2) 最坏:O(n^2) 优化后:坏:O(n)
* 空间复杂度:O(1)
* 稳定性:稳定
*/
public static void bubbleSort(int[] data) {
int size = data.length;
for (int i = 0; i < size - 1; i++) {
for (int j = 0; j < size - 1 - i; j++) {
if (data[j] > data[j + 1]) {
swap(data,j,j+1);
}
}
}
}
/**
* 选择排序算法
* 简单选择排序的基本思想:
* 第1趟,在待排序记录data[1]~data[n]中选出最小的记录,将它与data[1]交换;
* 第2趟,在待排序记录data[2]~r[n]中选出最小的记录,将它与data[2]交换;
* 以此类推,第i趟在待排序记录data[i]~data[n]中选出最小的记录,将它与data[i]交换,使有序序列不断增长直到全部排序完毕。
*
* 时间复杂度:O(n^2)
* 空间复杂度:O(1)
* 稳定性:不稳定
*/
public static void selectSort(int[] data) {
for (int i = 0; i < data.length - 1; i++) {// 做第i趟排序
int k = i;
for (int j = k + 1; j < data.length; j++) {// 选最小的记录
if (data[j] < data[k]) {
k = j; //记下目前找到的最小值所在的位置
}
}
//在内层循环结束,也就是找到本轮循环的最小的数以后,再进行交换
if (i != k) { //交换a[i]和a[k]
swap(data,i,k);
}
}
}
/**直接插入排序
直接插入排序就是从待排序列中选出一个元素,插入到已经有序的元素之中,直到所有的元素都插入到有序序列中所有的元素就全部有序了。
方法:将第一个元素看做是有序的元素(即待排序列的第一个元素看做是有序序列),然后我们将第二个元素和有序序列(即
第一个元素)作比较,按正确的序列插入到序列中去。然后在将第三个元素和前面有序序列(即整个待排序列的前两个元素)作比较,将第
三个插入到前两个元素中去,使得前三个元素有序。以此类推,直到所有的元素都有序。
时间复杂度:最好:有序:O(n) 最坏:O(n^2)
空间复杂度:O(1)
稳定性:稳定
*/
public static void insertSort1(int[] data) {
int size = data.length;
int key;
int i, j;
for (i = 1; i < size; i++) {
key = data[i];
for (j = i - 1; j >= 0; j--) {
if (key >= data[j]) {
break;
}
else {
data[j + 1] = data[j];
}
}
data[j + 1] = key;
}
}
public static void insertSort2(int[] data){
int size = data.length;
int i;
for(i = 1; i < size; i++)//
{
int after=data[i];
int before=i-1;//插入点初始化是inserter前面的一个元素
while(before>=0 && after<data[before])//寻找插入点
{
data[before+1]=data[before];
before--;//符合插入条件,插入点在往前移
}
data[before+1]=after;//插入
}
}
public static void insertSort3(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int j = i;
while (j > 0 && arr[j] < arr[j - 1]) {
swap(arr,j,j-1);
j--;
}
}
}
/*
希尔排序也称之为递减增量排序,他是对插入排序的改进。在第二步插入排序中,我们知道,插入排序对于近似已排好序的序列来说,效率很高,
可以达到线性排序的效率。但是插入排序效率也是比较低的,他一次只能将数据向前移一位。
比如如果一个长度为N的序列,最小的元素如果恰巧在末尾,那么使用插入排序仍需一步一步的向前移动和比较,要N-1次比较和交换。
希尔排序通过将待比较的元素划分为几个区域来提升插入排序的效率。
这样可以让元素可以一次性的朝最终位置迈进一大步,然后算法再取越来越小的步长进行排序,
最后一步就是步长为1的普通的插入排序的,但是这个时候,整个序列已经是近似排好序的,所以效率高。
*/
public static void shellSort(int[] data){
int size=data.length;
while(true)
{
size=size/2;
for(int d=0;d<size;d++)
{
for(int i=d+size;i<data.length;i=i+size)
{
int temp=data[i];
int j;
for(j=i-size;j>=0&&data[j]>temp;j=j-size)
{
data[j+size]=data[j];
}
data[j+size]=temp;
}
}
if(size==1)
{
break;
}
}
}
/*
快速排序:
*/
public static void quickSort(int[]data,int left,int right){
int i, j, t, temp;
if(left > right)
return;
temp = data[left]; //temp中存的就是基准数
i = left;
j = right;
while(i != j) { //顺序很重要,要先从右边开始找
while(data[j] >= temp && i < j)
j--;
while(data[i] <= temp && i < j)//再找右边的
i++;
if(i < j)//交换两个数在数组中的位置
{
t = data[i];
data[i] = data[j];
data[j] = t;
}
}
//最终将基准数归位
data[left] = data[i];
data[i] = temp;
quickSort(data, left, i-1);//继续处理左边的,这里是一个递归的过程
quickSort(data,i+1, right);//继续处理右边的 ,这里是一个递归的过程
}
/**
* 堆排序
* 时间复杂度:O(nlog2n)
* 空间复杂度:O(1)
* 稳定性:2 3 2` 不稳定
* https://www.cnblogs.com/0zcl/p/6737944.html#3939134
* */
public static void adjust(int[] data,int start,int end) {
//建立父节点指标和子节点指标
int dad = start;
int son = dad * 2 + 1;
while (son <= end) { //若子节点指标在范围内才做比较
if (son + 1 <= end && data[son] < data[son + 1]) //先比较两个子节点大小,选择最大的
son++;
if (data[dad] > data[son]) //如果父节点大于子节点代表调整完毕,直接跳出函数
return;
else { //否则交换父子内容再继续子节点和孙节点比较
swap(data,dad,son);
dad = son;
son = dad * 2 + 1;
}
}
}
//堆排序
public static void heapSort(int[] data,int len) {
int i;
//初始化,i从最後一个父节点开始调整
for (i = data.length / 2 - 1; i >= 0; i--)
adjust(data, i, data.length - 1);
//先将第一个元素和已排好元素前一位做交换,再重新调整,直到排序完毕
for (i = data.length - 1; i > 0; i--) {
swap(data,0,i);
adjust(data, 0, i - 1);
}
}
//归并排序
public static void Merge(int data[], int left, int mid, int right, int[] extra)
{
int left_i = left; // [left, mid)
int right_i = mid; // [mid, right)
int extra_i = left;
while (left_i < mid && right_i < right) {
if (data[left_i] <= data[right_i]) {
extra[extra_i++] = data[left_i++];
}
else {
extra[extra_i++] = data[right_i++];
}
}
while (left_i < mid) {
extra[extra_i++] = data[left_i++];
}
while (right_i < right) {
extra[extra_i++] = data[right_i++];
}
for (int i = left; i < right; i++) {
data[i] = extra[i];
}
}
// [left, right)
public static void __MergeSort(int data[], int left, int right, int[] extra)
{
if (left == right - 1) {
// 区间内只剩一个数,已经有序
return;
}
if (left >= right) {
// 区间内没有数了
return;
}
int mid = left + (right - left) / 2;
__MergeSort(data, left, mid, extra);//左边归并排序,使得左子序列有序
__MergeSort(data, mid, right, extra);//右边归并排序,使得右子序列有序
Merge(data, left, mid, right, extra);//将两个有序子数组合并操作
}
// 稳定
public static void mergeSort(int data[], int size)
{
int[] extra = new int [data.length] ;
__MergeSort(data, 0, size, extra);
}
public static void printArray(int[] data) {
// int size = data.length;
// for (int i = 0; i < size ; i++) {
// System.out.print(data[i] + " , ");
// }
/*
foreach的书写格式:
for(元素类型 元素名称 : 遍历数组(集合)(或者能进行迭代的)){
语句
}
*/
for (int i : data) {
System.out.print(i+" ");
}
System.out.println();
}
public static void swap(int[] data,int x,int y){
int a = data[x];
int b = data[y];
data[x] = b;
data[y] = a;
}
public static void main(String[] args) {
int[] arr = {9,8,7,6,5,4,3,2,1};
System.out.print("排序前:");
printArray(arr);
bubbleSort(arr);
System.out.print("冒泡排序后:\t");
printArray(arr);
selectSort(arr);
System.out.print("选择排序后:\t");
printArray(arr);
insertSort2(arr);
System.out.print("直接插入排序后:");
printArray(arr);
shellSort(arr);
System.out.print("希尔排序后:\t");
printArray(arr);
heapSort(arr,arr.length);
System.out.print("堆排序后:\t");
printArray(arr);
mergeSort(arr,arr.length);
System.out.print("归并排序后:\t");
printArray(arr);
quickSort(arr,0,arr.length-1);
System.out.print("快速排序后:\t");
printArray(arr);
}
}
java实现七大排序
最新推荐文章于 2024-07-23 15:27:37 发布