因为这学期上算法课,因为要准备蓝桥杯国赛,所以复习记录一下几个经典的算法 (T_T)。。。
时间复杂度 T(n) | 算法稳定性 | |
---|---|---|
冒泡排序 | O(n2) | 稳定 |
插入排序 | O(n2) | 稳定 |
堆排序 | O(n) | 不稳定 |
归并排序 | O(nlogn) | 稳定 |
快速排序 | O(nlogn) | 不稳定 |
1.冒泡排序
冒泡排序的基本思想:
对于n个元素的数组,算法执行n-1次;
对于第i次,从第一个元素开始,依次与后面元素进行比较,一直比较到n-i次;
如果该元素比后面元素大,则交换元素。
import java.util.Random;
/**
* @author: cuttle
* @Date: 2020/9/30 16:24
* @Description: 对产生的随机数据进行冒泡排序
*/
public class BubbleSort {
public int[] array;
public BubbleSort(int n){
array = new int[n];
initArray();
}
public void initArray(){
Random random = new Random(97);
for(int i = 0;i < array.length;i++){
array[i] = random.nextInt();
}
}
public void bubbleSort(){
for(int i = 1;i < array.length;i++){
boolean hasSwap = false;
for(int j = 0;j < array.length - i;j++){
if(array[j+1] < array[j]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
hasSwap = true;
}
}
if(!hasSwap){
break;
}
}
}
public void printArray(){
for(int i = 0;i < array.length;i++){
System.out.print(array[i] + " ");
}
System.out.println();
}
public static void main(String[]args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入用于排序的数据数量n:");
int n = sc.nextInt();
BubbleSort bs = new BubbleSort(n);
System.out.println("排序前:");
bs.printArray();
System.out.println("----------------开始排序----------------");
long start = System.currentTimeMillis();
bs.bubbleSort();
long end = System.currentTimeMillis();
System.out.println("----------------结束排序----------------");
System.out.println("冒泡排序所用时间" + (end - start) + "ms");
System.out.println("排序后:");
bs.printArray();
}
}
2.插入排序
插入排序的算法思想:
假设前i-1个元素已经排好,现在考虑第i(2 ≤ i ≤ n)个元素;
首先将第i个元素赋值给X;
X与第i-1、i-2…1个元素比较;
如果大于X,那么右移,将X放入空出的位置。
import java.util.Random;
/**
* @author: cuttle
* @Date: 2020/9/30 17:24
* @Description: 对产生的随机数据进行插入排序
*/
public class InsertionSort {
public int[] array;
int x;
int j;
public InsertionSort(int n){
array = new int[n];
init();
}
public void init(){
Random random = new Random(97);
for(int i = 0;i < array.length;i++){
array[i] = random.nextInt();
}
}
public void insertionSort(){
for(int i = 1;i < array.length;i++){
x = array[i];
j = i - 1;
while(j >= 0 && array[j] > x){
array[j+1] = array[j];
j--;
}
}
}
public void printArray(){
for(int i = 0;i < array.length;i++){
System.out.print(array[i] + " ");
}
System.out.println();
}
public static void main(String[]args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入用于排序的数据数量n:");
int n = sc.nextInt();
InsertionSort is = new InsertionSort(n);
System.out.println("排序前:");
is.printArray();
System.out.println("----------------开始排序----------------");
long start = System.currentTimeMillis();
is.insertionSort();
long end = System.currentTimeMillis();
System.out.println("----------------结束排序----------------");
System.out.println("插入排序所用时间" + (end - start) + "ms");
System.out.println("排序后:");
is.printArray();
}
}
3.堆排序
堆排序的算法思想:
首先将输入的数据创建为一个堆;
交换堆中的第一个元素和最后一个元素,则新的最后一个元素即是已经排好序的元素;
将堆的大小减1,并对第1个元素执行节点下移操作。
继续该过程,当堆的大小减为1时,就完成了排序。
import java.util.Random;
/**
* @author: cuttle
* @Date: 2020/9/30 16:24
* @Description: 对产生的随机数据进行堆排序
*/
public class HeapSort {
public int[] array;
public int n;
public HeapSort(int n){
array = new int[n];
this.n = n;
initArray();
}
public void initArray(){
Random random = new Random(97);
for(int i = 0;i < n;i++){
array[i] = random.nextInt();
}
}
public void makeHeap(){
for(int i = n / 2 - 1;i >= 0;i--){
siftDown(n,i);
}
}
public void siftDown(int n,int i){
boolean done = false;
while(!done && (i = 2 * i + 1) < n){
if(i + 1 < n && array[i+1] > array[i])
i = i + 1;//找到子节点中比较大的一个
if(array[(i-1)/2] < array[i]){
int temp = array[i];
array[i] = array[(i-1)/2];
array[(i-1)/2] = temp;
}else{
done = true;
}
}
}
public void heapSort(){
makeHeap();
for(int i = n - 1;i > 0;i--){
int temp = array[0];
array[0] = array[i];
array[i] = temp;
siftDown(i,0);
}
}
public void printArray(){
for(int i = 0;i < array.length;i++){
System.out.print(array[i] + " ");
}
System.out.println();
}
public static void main(String[]args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入用于排序的数据数量n:");
int n = sc.nextInt();
HeapSort hs = new HeapSort(n);
System.out.println("排序前:");
hs.printArray();
System.out.println("----------------开始排序----------------");
long start = System.currentTimeMillis();
hs.heapSort();
long end = System.currentTimeMillis();
System.out.println("----------------结束排序----------------");
System.out.println("堆排序所用时间" + (end - start) + "ms");
System.out.println("排序后:");
hs.printArray();
}
}
4.归并排序
归并排序算法基本思想:
归并排序是一个典型的分治算法:
1.分解:首先将排序数组分解为左右两个等大的不重叠的子数组;
2.解决:递归;
3.合并:将两个已经有序的数组合并为一个有序的数组。
import java.util.Random;
/**
* @author: cuttle
* @Date: 2020/10/14 16:34
* @Description: 对产生的随机数据进行归并排序
*/
public class MergeSort {
public int[] array;
public MergeSort(int n){
array = new int[n];
initArray();
}
public void initArray(){
Random random = new Random(97);
for(int i = 0;i < array.length;i++){
array[i] = random.nextInt();
}
}
public void mergeSort(int low,int high){
if(low < high){
int mid = (low + high) / 2;
mergeSort(low,mid);
mergeSort(mid+1,high);
merge(low,mid,high);
}
}
public void merge(int p,int q,int r){
int i = p;
int j = q + 1;
int k = p;
int[] b = new int[r + 1];
while (i <= q && j <= r){
if(array[i] < array[j]){
b[k++] = array[i++];
} else {
b[k++] = array[j++];
}
}
if(i == q+1){
for(;j <= r;j++){
b[k++] = array[j];
}
}else {
for(;i <= q;i++){
b[k++] = array[i];
}
}
for(int m = p;m <= r;m++){
array[m] = b[m];
// System.out.print(b[m]+" ");
}
// System.out.println();
}
public void printArray(){
for(int i = 0;i < array.length;i++){
System.out.print(array[i] + " ");
}
System.out.println();
}
public static void main(String[]args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入用于排序的数据数量n:");
int n = sc.nextInt();
MergeSort ms = new MergeSort(n);
System.out.println("排序前:");
ms.printArray();
System.out.println("----------------开始排序----------------");
long start = System.currentTimeMillis();
ms.mergeSort(0,n-1);
long end = System.currentTimeMillis();
System.out.println("----------------结束排序----------------");
System.out.println("归并排序所用时间" + (end - start) + "ms");
System.out.println("排序后:");
ms.printArray();
}
}
5.快速排序
快速排序算法基本思想:
使用分治策略把待排序数据序列分为两个子序列:
1.挑出一个元素,成为“枢纽”元素pivot;
2.分区:将所有比枢纽元素小的元素放在枢纽元素前面,所有比枢纽元素大的元素放在枢纽元素后面;
3.将枢纽元素前面和后面的子序列用步骤2递归。
import java.util.Random;
/**
* @author: cuttle
* @Date: 2020/10/14 16:35
* @Description: 对产生的随机数据进行快速排序算法
*/
public class QuickSort {
public int[] array;
public QuickSort(int n){
array = new int[n];
initArray();
}
public void initArray(){
Random random = new Random(97);
for(int i = 0;i < array.length;i++){
array[i] = random.nextInt();
}
}
public void quickSort(int low,int high){
if(low < high){
int p = partition(low,high);
quickSort(low,p - 1);
quickSort(p + 1,high);
}
}
public int partition(int low,int high){
int pivot = array[high];
int i = low - 1;
for(int j = low;j <= high-1;j++){
if(array[j] < pivot){
i = i + 1;
if(i < j){
swap(i,j);
}
}
}
if(array[high] < array[i + 1]){
swap(high,(i + 1));
}
return i + 1;
}
public void swap(int i,int j){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public void printArray(){
for(int i = 0;i < array.length;i++){
System.out.print(array[i] + " ");
}
System.out.println();
}
public static void main(String[]args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入用于排序的数据数量n:");
int n = sc.nextInt();
QuickSort qs = new QuickSort(n);
System.out.println("排序前:");
qs.printArray();
System.out.println("----------------开始排序----------------");
long start = System.currentTimeMillis();
qs.quickSort(0,n - 1);
long end = System.currentTimeMillis();
System.out.println("----------------结束排序----------------");
System.out.println("快速排序所用时间" + (end - start) + "ms");
System.out.println("排序后:");
qs.printArray();
}
}