java 7个数排序_Java数据结构(七)—— 排序算法

排序算法(Sort Algorithm)

排序算法介绍和分类

将一组数据,依指定顺序进行排列

排序的分类

内部排序

指将需要处理的所有数据都加载到内部存储器中进行排序

外部排序

数据量过大,无法全部加载到内存中,需借助外部存储进行排序

常见的排序算法

99b15646e1b10814c77239d5cbb4521b.png

冒泡排序(Bubble Sort)

基本思想

通过对待排序序列从前向后(从下表较小的元素 开始),依次比较相邻元素的值,若发现逆序,交换相邻元素的值

基本代码

public static void bubbleSorting(int[] arr){

for (int i = 0; i < arr.length-1; i++) {

for (int j = 0; j < arr.length-i-1; j++) {

if (arr[j]>arr[j+1]){

int temp = arr[j];

arr[j] = arr[j+1];

arr[j+1] = temp;

}

}

}

for (int i = 0; i < arr.length; i++) {

System.out.println(arr[i]);

}

}

优化

因为排序过程 中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,,因此要在排序过程中设置一个标志flag判断元素是否交换,从而减少不必要的比较

优化后代码

public static void bubbleSorting(int[] arr){

int temp = 0;

//标志变量,表示是否进行过交换

boolean flag = false;

for (int i = 0; i < arr.length-1; i++) {

for (int j = 0; j < arr.length-i-1; j++) {

if (arr[j]>arr[j+1]){

flag = true;

temp = arr[j];

arr[j] = arr[j+1];

arr[j+1] = temp;

}

}

if (flag = false){//在一趟排序中一次都没有交换

break;

}else {

flag = false;//重置flag进行下次判断

}

}

//       for (int i = 0; i < arr.length; i++) {

//           System.out.print(arr[i]);

//       }

//       System.out.println();

}

选择排序(Select Sort)

基本思想

第一次从arr[0]~arr[n-1]中选取最小值,与arr[0]交换,然后一次从后面的数据选取最小值,与数组前的值交换

public static void selectSorting(int[] arr){

for (int i = 0; i < arr.length-1; i++) {

int temp = arr[i];

for (int j = i; j < arr.length; j++) {

if (arr[i]>arr[j]){//从小到大排序

temp = arr[j];

arr[j] = arr[i];

arr[i] = temp;

}

}

}

for (int i = 0; i < arr.length; i++) {

System.out.print(arr[i]);

}

System.out.println();

}

插入排序(Insert Sort)

基本思想

插入排序属于内部排序,是对于排序的元素以插入的方式 找寻该元素的适当位置,以达到排序的目的

把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序吗一次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,是指成为新的有序表。

代码实现

public static void insertionSorting(int[] arr){

int insert = arr[0];//第一个插入的数,直接插入

int insertIndex = 0;//arr[1]起那面这个数的下标

arr[insertIndex] = insert;

for (int i = 1; i < arr.length-1; i++) {

//insertIndex >= 0,保证给insert找插入位置时不越界

//insert < arr[insertIndex,待插入的数即arr[insertIndex]后移

insert = arr[i];

insertIndex = i - 1;

while (insertIndex >= 0 && insert < arr[insertIndex]){

arr[insertIndex+1] = arr[insertIndex];

insertIndex--;

}

arr[insertIndex+1] = insert;

}

System.out.println(Arrays.toString(arr));

}

问题

若数据过于小,后移的次数较多影响效率

希尔排序(Shell Sort)

希尔排序是简单排序改进后更高效的排序

也称缩小增量排序

基本思想

把记录按下标的一定增量分组

对每组使用直接插入排序算法

随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法终止

交换式算法实现

/**

* 交换法,实现希尔排序,效率低

* @param arr

*/

public static void shellSortExchange(int[] arr){

//将数据根据数组长度进行分组

int len = (int) Math.floor(arr.length/2);

int temp = 0;

while (len>=1){

for (int i = len; i < arr.length; i++) {

//遍历各组所有的元素,(共有len组,每组2个元素),步长len

for (int j = i-len; j >= 0; j -= len) {

//从小到大排序

//如果当前元素大于加上步长的元素,需要交换

if (arr[j] >  arr[j+len]){

temp = arr[j];

arr[j] = arr[j+len];

arr[j+len] = temp;

}

}

}

len = (int) Math.floor(len/2);

}

System.out.println(Arrays.toString(arr));

}

移位式算法实现

/**

* 移位式,效率高

* @param arr

*/

public static void shellSortShift(int[] arr){

int len = (int) Math.floor(arr.length/2);

int temp = 0;

//增量len,并逐步缩小增量

while (len >= 1){

//从第len个元素,诸葛对其所在的组进行直接插入排序

for (int i = len; i < arr.length; i++) {

int j = i;

temp = arr[j];

if (arr[j]

while (j-len >= 0 && temp < arr[j-len]){

//移动

arr[j] = arr[j-len];

j -= len;

}

//退出循环后找到了插入的位置

arr[j] = temp;

}

}

len = (int) Math.floor(len/2);

}

System.out.println(Arrays.toString(arr));

}

快速排序(Quick Sort)

快速排序是对冒泡排序的一种改进

基本思想

通过一趟排序将要排序的数据分割为独立的两部分

一部分所有的数据都比另一部分所有的数据小

按上述方法对两部分数据进行快速排序

整个排序过程可以递归进行,达到整个数据编程有序序列

找一个基准,将数据序列分成两部分

代码实现

/**

* 快速排序

* @param arr

* @param left

* @param right

*/

public static void quickSort(int[] arr,int left,int right){

int l = left;//左下标

int r = right;//右下标

int pivot = arr[(left+right)/2];//基准数

int temp = 0;//临时变量

//左边索引大于等于右边索引时结束循环

//将比pivot小的数据放到左边,大的放到右边

while (l < r){

//在pivot左边找到大于或等于pivot的值,才退出

while (arr[l] < pivot){

l += 1;

}

//在pivot右边找到小于或等于pivot的值,才退出

while (arr[r] > pivot){

r -= 1;

}

//l >= r,pivot左右两边的值,已按照左边全部是小于等于pivot的值

//右边大于等于pivot的值

if (l >= r){

break;

}

//交换

temp = arr[l];

arr[l] = arr[r];

arr[r] = temp;

//如果交换完后发现arr[l] == pivot,则r--,前移一步

if (arr[l] == pivot){

r -= 1;

}

//如果交换完后发现arr[r] == pivot,则l++,后移一步

if (arr[r] == pivot){

l += 1;

}

}

//如果l == r,必须l++,r--,否则会出现栈溢出

if (l == r){

l++;

r--;

}

//向左递归

if (left < r){

quickSort(arr,left,r);

}

//向右递归

if(right > l){

quickSort(arr,l,right);

}

}

归并排序(Merge Sort)

归并排序是利用归并的思想实现的排序方法,采用分治的策略。

基本思想

4eb35372816b3ff4816564cb59d70ef2.png

最后一次合并

33bb7677b138325ecf45e735cdc915d2.png

代码实现

/**

* 归并排序

* @param arr

* @param left

* @param right

* @param temp

*/

public static void mergeSort(int[] arr,int left,int right,int[] temp){

if (left < right){

int mid = (left + right) / 2;

//向左递归进行分解

mergeSort(arr,left,mid,temp);

//向右递归进行分解

mergeSort(arr,mid+1,right,temp);

//到合并

merge(arr,left,mid,right,temp);

}

}

/**

* 归并排序合并的方法

* @param arr   待排序的数组

* @param left 左边有序序列的初始索引

* @param mid   中间索引

* @param right 右边索引

* @param temp 中转临时数组

*/

public static void merge(int[] arr,int left,int mid,int right,int[] temp){

//初始化i,j

int i = left; //左边序列的初始索引

int j = mid + 1; //右边有序序列的初始索引

int t = 0; //temp的索引

//(一)

//先把左右两边(有序)的数据按规则填充到temp数组

//直到左右两边有一边的有序序列处理完毕

while (i <= mid && j <= right){

//左边有序序列的当前元素小于或等于右边有序序列的当前元素

if (arr[i] <= arr[j]){

//将左边当前数据加入到temp中

// 并且将temp索引t和右边索引i,分别+=1

temp[t] = arr[i];

t += 1;

i += 1;

}else {//左边有序序列的当前元素大于右边有序序列的当前元素

//将右边当前数据加入到temp中

// 并且将temp索引t和右边索引j,分别+=1

temp[t] = arr[j];

t += 1;

j += 1;

}

}

//(二)

//把有剩余的一边的数据一次全部填充到temp

while (i <= mid){//左边还有剩余元素,全部填充到temp

temp[t] = arr[i];

t +=  1;

i += 1;

}

while (j <= right){//右边还有剩余元素,全部填充到temp

temp[t] = arr[j];

t +=  1;

j += 1;

}

//(三)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值