package structure;
/**
* 简单排序的几种方式:冒泡排序、选择排序和插入排序,时间复杂度基本都为O(n*n)<br>
* 冒泡排序效率最低,选择排序则减少了元素交换的次数,而插入排序是3种方式中效率最高的<br>
* 特别是当元素基本有序的情况下, 插入排序其平均时间复杂度接近O(n) <br />
*
* 除此之外复杂但更高效的排序方式还有:希尔排序和快速排序
*
* @author yli
*
*/
public class SortDemo {
public static void main(String[] args) {
// 冒泡排序:升序
popSortAsc();
// 冒泡排序:降序
popSortDesc();
// 选择排序:升序
selectedSortAsc();
// 选择排序:降序
selectedSortDesc();
// 插入排序:升序
insertSortAsc();
// 插入排序:降序
insertSortDesc();
}
/**
* 冒泡排序:升序方式排序<br>
* 冒泡排序特点:n个元素需要执行(n-1)次冒泡排序,第i轮冒泡有 (n-1-i)个元素需要两两比较<br>
* 并且两两比较,只要满足比较条件,则相邻元素就交换,这其实就是和选择排序最大的区别
*/
public static void popSortAsc() {
int[] a = { 10, 4, 3, 6, 5, 7, 2, 1, 9, 8 };
int temp;
// n 个元素,需要执行 n-1 轮冒泡排序
int popCount = a.length - 1;
for (int i = 0; i < popCount; i++) {
// 第i轮冒泡就还有 (n-1-i)个元素需要两两比较
for (int j = 0; j < popCount - i; j++) {
if (a[j] > a[j + 1]) {
// 相邻两个元素比较只要符合条件,那么两个元素就进行交换
// 并且发现外层循环和内部循环中的元素没有关系
// 因此外层循环是计算:总共需要执行多少轮冒泡排序
// 而内部循环是:对剩余还未排序的元素进行一轮冒泡排序
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
print(a);
}
/**
* 冒泡排序:降序方式排序
*/
public static void popSortDesc() {
int[] a = { 10, 4, 3, 6, 5, 7, 2, 1, 9, 8 };
int temp;
int popCount = a.length - 1;
for (int i = 0; i < popCount; i++) {
for (int j = 0; j < popCount - i; j++) {
// 升序和降序,只要改变比较方式即可
if (a[j] < a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
print(a);
}
/**
* 比较排序:升序方式排序<br>
* 比较排序特点:和冒泡排序类似,n个元素,需要执行(n-1)轮选择排序<br>
* 执行第i轮排序,假设a[i]为最小元素,从剩余的a[i+1]到a[len-1]中记录比a[i]还小的元素的位置<br>
* 最后再拿a[i]和a[minIndex]进行交换,和冒泡排序相比,速度更快,因为节省了多次交换的时间<br>
* 对于那些交换需要花费更多时间的编程语言来说,选择排序无疑比冒泡排序更优<br>
*/
public static void selectedSortAsc() {
int[] a = { 10, 4, 3, 6, 5, 7, 2, 1, 9, 8 };
int minIndex;
int temp;
for (int i = 0; i < a.length - 1; i++) {
// 假设a[i]是当前最小元素
minIndex = i;
// 从a[i+1]到a[len-1]中选出比a[i]还小的元素
for (int j = i + 1; j < a.length; j++) {
// 和冒泡排序相比,只从待排序元素中选出最小元素,并记录其位置
if (a[minIndex] > a[j]) {
minIndex = j;
}
}
// 等一轮选择排序执行完之后再交换
if (i != minIndex) {
temp = a[i];
a[i] = a[minIndex];
a[minIndex] = temp;
}
}
print(a);
}
/**
* 比较排序:降序方式排序
*/
public static void selectedSortDesc() {
int[] a = { 10, 4, 3, 6, 5, 7, 2, 1, 9, 8 };
int minIndex;
int temp;
for (int i = 0; i < a.length - 1; i++) {
minIndex = i;
for (int j = i + 1; j < a.length; j++) {
if (a[minIndex] < a[j]) {
minIndex = j;
}
}
if (i != minIndex) {
temp = a[i];
a[i] = a[minIndex];
a[minIndex] = temp;
}
}
print(a);
}
/**
* 插入排序:升序方式排序<br>
* 插入排序的特点:局部有序,待排序的元素在有序的元素中找到一个合适的位置插入<br>
* 大约比冒泡排序快1倍,比选择排序略快<br>
* 这种排序方式特别适合基本有序的元素排序,其排序速度接近 O(n)<br>
* 不过正常情况下,其排序速度也要计算为 O(n*n)
*
*/
public static void insertSortAsc() {
int[] a = { 10, 4, 3, 6, 5, 7, 2, 1, 9, 8 };
int j;
int temp;
// 假设a[0]为局部有序的元素(因为只有一个,所以肯定是有序)
// 然后从a[1]开始往局部有序的元素中插入新元素
for (int i = 1; i < a.length; i++) {
j = i;
// 第[i]轮排序,要插入的新元素就是 a[i]
temp = a[i];
// 然后找到新元素在局部有序元素中的位置
while (j > 0 && a[j - 1] > temp) {
a[j] = a[j - 1];
j--;
}
a[j] = temp;
}
print(a);
}
/**
* 插入排序:降序方式排序
*/
public static void insertSortDesc() {
int[] a = { 10, 4, 3, 6, 5, 7, 2, 1, 9, 8 };
int j;
int temp;
for (int i = 1; i < a.length; i++) {
j = i;
temp = a[i];
// 升序和降序,只要改变比较方式即可
while (j > 0 && a[j - 1] < temp) {
a[j] = a[j - 1];
j--;
}
a[j] = temp;
}
print(a);
}
private static void print(int[] arr) {
for (int temp : arr) {
System.out.print(temp + "\t");
}
System.out.println();
}
}
简单排序:冒泡排序、选择排序和插入排序
最新推荐文章于 2020-12-24 11:23:17 发布