您的位置:首页 > 理论基础 > 数据结构算法

【算法和数据结构】—— 1.选择排序、插入排序

2017-07-11 19:05 567 查看
1、O(n^2)排序算法之选择排序**

2、O(n^2)排序算法之插入排序**

一、O(n^2)排序算法之选择排序

1、实现思路: 从最左边下标开始,将该下标的元素和它右边所有元素比较,每一趟遍历找出最小元素的下标,然后将最小下标的元素和该下标元素互换,即每一趟遍历都将最小值放在开始遍历的最左的下标位置

2、int类型数组的选择排序算法

package com.algorithm.demo;

/**
*
* @author eric
* 从最左边下标开始,将该下标的元素和它右边所有元素比较,每一趟遍历找出最小元素的下标
* 然后将最小下标的元素和每一趟遍历开始的最左边下标的元素互换,即每一趟遍历都将最小值放在开始遍历的最左的下标位置
*/
public class SelectionSort {

// 我们的算法类不允许产生任何实例
private SelectionSort() {
}

public static void sort(int[] arr) { // 左边要比较到倒数第二个下标

int len = arr.length;
for (int i = 0; i < len - 1; i++) {
// 寻找[i, n)区间里的最小值的索引
int minIndex = i;
for (int j = i + 1; j < len; j++) {
// 每一趟遍历找出最小元素的下标
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// 交换开始遍历的最左和最小下标的元素
swap(arr, i, minIndex);
}
}

/**
* 交换两个下标的元素
*
* @param arr 要排序的数组
* @param i 下标1
* @param j 下标2
*/
private static void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}

public static void main(String[] args) {

int[] arr = { 10, 9, 8, 7, 6, 5, 4, 1, 2, 3, 0 };
SelectionSort.sort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
System.out.print(' ');
}
System.out.println();
}

}


3、实现了Comparable接口的类,支持泛型排序

1、实现了Comparable接口的类

package com.algorithm.demo;

/**
*
* @author eric
*
*/
// 实现了Comparable接口的类,支持排序
public class Student implements Comparable<Student> {

private String name;
private int score;

public Student(String name, int score) {
this.name = name;
this.score = score;
}

// 定义Student的compareTo函数
// 如果分数相等,则按照名字的字母序排序
// 如果分数不等,则分数高的靠前
@Override
public int compareTo(Student that) {

if (this.score == that.score)
return this.name.compareTo(that.name);

if (this.score < that.score)
return 1;
else if (this.score > that.score)
return -1;
else // this.score == that.score
return 0;
}

// 定义Student实例的打印输出方式
@Override
public String toString() {
return "Student: " + this.name + " " + Integer.toString(this.score);
}
}


2、支持泛型排序实现类

package com.algorithm.demo;
public class SelectionSort2 {
// 我们的算法类不允许产生任何实例
private SelectionSort2(){}

/**
* 支持泛型比较
* @param arr
*/
public static <T extends Comparable<T>> void sort(T[] arr){

int len = arr.length;
for (int i = 0; i < len - 1; i++) {
// 寻找[i, n)区间里的最小值的索引
int minIndex = i;
for (int j = i + 1; j < len; j++) {
// 使用compareTo方法比较两个Comparable对象的大小
if (arr[j].compareTo(arr[minIndex]) < 0) {
minIndex = j;
}
}
swap(arr, i, minIndex);
}
}

private static void swap(Object[] arr, int i, int j) {
Object t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}

public static void main(String[] args) {

// 测试Integer
Integer[] a = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
SelectionSort2.sort(a);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
System.out.print(' ');
}
System.out.println();

// 测试Double
Double[] b = { 4.4, 3.3, 2.2, 1.1 };
SelectionSort2.sort(b);
for (int i = 0; i < b.length; i++) {
System.out.print(b[i]);
System.out.print(' ');
}
System.out.println();

// 测试String
String[] c = { "D", "C", "B", "A" };
SelectionSort2.sort(c);
for (int i = 0; i < c.length; i++) {
System.out.print(c[i]);
System.out.print(' ');
}
System.out.println();

// 测试自定义的类 Student
Student[] d = new Student[4];
d[0] = new Student("D", 90);
d[1] = new Student("C", 100);
d[2] = new Student("B", 95);
d[3] = new Student("A", 95);
SelectionSort2.sort(d);
for (int i = 0; i < d.length; i++)
System.out.println(d[i]);
}
}


二、插入排序

1、普通插入排序实现思路:从右边开始起将相邻元素两两比较后排序。第一趟将最左边两个元素比较排序,右边的大于(或小于)左边的话,两者调换元素位置;第二趟从最左边三个元素右边开始将两两比较排序,…… 最后一次是所有元素的相邻元素从右边开始将两两比较排序

for (int i = 1; i < len; i++) {
// 寻找元素arr[i]合适的插入位置
for( int j = i; j > 0 && arr[j].compareTo(arr[j-1]) < 0 ; j--) {
swap(arr, j, j-1);
}
}


改进版插入排序:

耗时改进点:每次两两比较后如果有需要都互换位置(耗时:交换每次都需要三次赋值操作,访问数组和访问相应下标的数组数据),改进后每次将每次都要交换操作变成有必要时一次赋值来节省时间

实现思路:因为每一趟遍历排序后(0 —> i-1下标的元素已排好序); 下一趟开始遍历前先复制一份i 下标的元素,然后将i 下标元素和 i - 1 下标元素比较,没互换的需要,此趟直接排序完成(非常省时);如有需要互换,将 i - 1下标元素放到 i 下标位置,原复制出来的 i 下标元素值再和 i - 2下标元素比较,如有需要互换,将 i - 2 下标元素放到 i - 1 下标位置;没需要互换,将复制出来的 i 下标元素值放在 i - 1 下标位置,此趟排序完成 … 即上一趟排好序的数不断往前推, i 下标元素找到属于自己的位置, 就是每一趟排序完成。

int len = arr.length;
for (int i = 1; i < len; i++) {
T e = arr[i];
int j = i; // j 保存元素e应该插入的位置
for( ; j > 0 && arr[j-1].compareTo(e) > 0 ; j--) {
arr[j] = arr[j-1]; // 前一趟排好序的数组和e值比较,不断往前推移
}
arr[j] = e;
}


时间复杂度:==> 对于几乎有序的数组,插入排序效果非常高,时间复杂度近乎O(n)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐