//
// sort.cpp
// LeetCode
//
// Created by huangyi on 2019/4/11.
// Copyright © 2019 Leetcode. All rights reserved.
//
#include
#include
using namespace std;
int len = 5;
void bubbleSort(int a[]) {
for(int i = 0; i < len; i++) {
for(int j = 0; j < len - 1 - i; j++) {
if(a[j] > a[j + 1]) {
swap(a[j], a[j+1]);
}
}
}
}
void selectSort(int a[]) {
for(int i = 0; i < len; i++) {
int min = i;
//每次从从i+1往后选一个最小的数和a[i]交换
for(int j = i + 1; j < len; j++) {
if(a[j] < a[min]) {
min = j;
}
}
swap(a[i], a[min]);
}
}
void insertSort(int a[]) {
for(int i = 1; i < len; i++) {
for(int j = i; j > 0; j--) {
while(a[j] < a[j-1]) {
swap(a[j], a[j-1]);
}
}
}
}
//希尔排序,分组进行插入排序
void shellSort(int a[]) {
int h = 1;
while(h < len / 3) {
h = 3 * h + 1;
}
while(h >= 1) {
for(int i = h; i < len; i ++) {
for(int j = i; j >= h; j-=h) {
while(a[j] < a[j-h]) {
swap(a[j], a[j - h]);
}
}
}
h = h / 3;
}
}
void merge(int a[], int low, int middle, int high) {
//定义一个辅助数组
int helper[len];
//将原数组元素拷到辅助数组
for(int i = low; i <= high; i++) {
helper[i] = a[i];
}
int helperLeft = low;
int helperRight = middle + 1;
int current = low;
while(helperLeft <= middle && helperRight <= high) {
if(helper[helperLeft] <= helper[helperRight]) {
a[current] = helper[helperLeft];
helperLeft++;
} else {
a[current] = helper[helperRight];
helperRight++;
}
current++;
}
int remain = middle - helperLeft;
for(int i = 0; i <= remain; i++) {
a[current + i] = helper[helperLeft + i];
}
}
void mergeSort(int a[], int low, int high) {
if(low < high) {
int middle = low + (high - low) / 2;
//排序左半部分
mergeSort(a, low, middle);
//排序右半部分
mergeSort(a, middle + 1, high);
//归并
merge(a, low, middle, high);
}
}
int paration(int a[], int left, int right) {
//取一个基准数
int pivot = a[left];
//保证左指针左侧元素都不大于切分元素,右指针右侧元素不小于切分元素
while(left < right) {
//从右往左找到第一个比pivot小的元素
while(left < right && a[right] >= pivot) {
right--;
}
a[left] = a[right];
//从左往右扫描找到第一个比pivot大的元素
while(left < right && a[left] <= pivot) {
left++;
}
a[right] = a[left];
}
a[left] = pivot;
return left;
}
void quickSort(int a[], int left, int right) {
if(left < right) {
int index = paration(a, left, right);
quickSort(a, left, index - 1);
quickSort(a, index + 1, right);
}
}
void buildMaxHeap(int a[], int lastIndex) {
for(int i = (lastIndex-1)/2; i >= 0; i--) {
int k = i;
while(k*2 + 1 <= lastIndex) {
int biggerIndex = 2 * k + 1;
if(biggerIndex < lastIndex) {
if(a[biggerIndex] < a[biggerIndex + 1]) {
biggerIndex++;
}
}
if(a[k] < a[biggerIndex]) {
swap(a[k], a[biggerIndex]);
k = biggerIndex;
} else {
break;
}
}
}
}
void heapSort(int a[]) {
for(int i = 0; i < len - 1; i++) {
buildMaxHeap(a, len - 1 - i);
swap(a[0], a[len - 1 - i]);
}
}
int main() {
int a[5] = {7, 6, 8, 3, 5};
//bubbleSort(a);
//selectSort(a);
//insertSort(a);
//shellSort(a);
mergeSort(a, 0, 5);
//quickSort(a, 0, 5);
//heapSort(a);
for(int i = 0; i < len; i++) {
printf("%d ", a[i]);
}
return 0;
}
基本思想:在要排序的一组数中,假设前面(n-1)个数已经有序,现在要把第n个数插到前面的有序数中,
使得这n个数也是有序的。如此反复循环,直到全部有序。
import java.util.*;
public class InsertSort {
public static void main(String args[]){
int a[] = {49,38,65,97,76};
int temp = 0;
for(int i=1;i<a.length;i++){
int j=i-1;
temp=a[i];
for(;j>=0&&temp<a[j];j--){
a[j+1]=a[j];//将大于temp的值整体后移一位
}
a[j+1]=temp;
}
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
}
}
最佳情况:O(n)
最坏情况:O(n^2)
平均时间复杂度:O(n^2)
空间复杂度:O(1)
稳定排序算法
基本思想:先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d。
对每组中全部元素进行直接插入排序,然后再用一个较小的增量对它进行分组,在每组中再进行直接插入排序。
当增量减到1,进行直接插入排序后,排序完成。
import java.util.*;
public class ShellFort {
public static void main(String args[]){
int a[] = {49,38,65,97,76};
int temp = 0;
double d1=a.length;
while(true){
d1=Math.ceil(d1/2);
int d = (int) d1;
for(int x=0;x<d;x++){
for(int i=x+d;i<a.length;i+=d){
int j=i-d;
temp=a[i];
for(;j>=0&&temp<a[j];j-=d){
a[j+d]=a[j];
}
a[j+d]=temp;
}
}
if(d==1){
break;
}
}
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
}
}
最佳情况:O(nlogn)
最坏情况:O(nlogn)
平均时间复杂度:O(nlogn)
空间复杂度:O(1)
不稳定排序算法
基本思想:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;
然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止
import java.util.*;
public class SelectSort {
public static void main(String args[]){
int a[] = {49,38,65,97,76};
int position=0;
for(int i=0;i<a.length;i++){
int j=i+1;
position=i;
int temp=a[i];
for(;j<a.length;j++){
if(a[j]<temp){
temp=a[j];
position=j;
}
}
a[position]=a[i];
a[i]=temp;
}
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
}
}
最佳情况:O(n^2)
最差情况:O(n^2)
平均时间复杂度:O(n^2)
空间复杂度:O(1)
不稳定排序算法
基本思想:堆排序是一种树形选择排序,是对直接选择排序的优化。
堆的定义:具有n个元素的序列(h1,h2…hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,…,n/2)时称为堆。
堆顶元素(即第一个元素)必为最大项(大顶堆)。
完全二叉树可以很直观地表示堆的结构。
堆排序需要两个过程
import java.util.*;
public class Test {
private static void swap(int[] data,int i,int j){
int tmp=data[i];
data[i]=data[j];
data[j]=tmp;
}
private static void buildMaxHeap(int[] data,int lastIndex){
for(int i=(lastIndex-1)/2;i>=0;i--){
int k=i;
while(k*2+1<=lastIndex){
int biggerIndex=2*k+1;
if(biggerIndex<lastIndex){
if(data[biggerIndex]<data[biggerIndex+1]){
biggerIndex++;
}
}
if(data[k]<data[biggerIndex]){
swap(data,k,biggerIndex);
k=biggerIndex;
}
else{
break;
}
}
}
}
public static void heapSort(int[] a){
System.out.println("开始排序");
int arrayLength=a.length;
for(int i=0;i<arrayLength-1;i++){
buildMaxHeap(a,arrayLength-1-i);
swap(a,0,arrayLength-1-i);
System.out.println(Arrays.toString(a));
}
}
public static void main(String[] args){
int a[] = {49,38,65,97,76};
heapSort(a);
}
}
最佳情况:O(nlogn)
最坏情况:O(nlogn)
平均时间复杂度:O(nlogn)
空间复杂度:O(1)
不稳定排序算法
基本思想:在要排序的一组数中。对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,
让较大的数往下沉,较小的往上冒。
即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
import java.util.*;
public class BubbleSort {
public static void main(String[] args){
int a[] = {49,38,65,97,76};
int temp=0;
for(int i=0;i<a.length-1;i++){
for(int j=0;j<a.length-1-i;j++){
if(a[j]>a[j+1]){
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
}
}
最佳情况:O(n)
最差情况:O(n^2)
平均时间复杂度:O(n^2)
空间复杂度为O(1)
稳定排序算法
基本思想:选择一个基准元素,通常选择第一个元素或者最后一个元素,
通过一趟扫描,将待排序序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,
此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。
import java.util.*;
public class Test {
public static int getMiddle(int[] list,int low,int high){
int tmp=list[low];
while(low<high){
while(low<high&&list[high]>=tmp){
high--;
}
list[low]=list[high];
while(low<high&&list[low]<=tmp){
low++;
}
list[high]=list[low];
}
list[low]=tmp;
return low;
}
public static void quickSort(int[] list, int low,int high){
if(low<high){
int middle=getMiddle(list, low, high);
quickSort(list,low,middle-1);
quickSort(list,middle+1,high);
}
}
public static void quick(int[] a2){
if(a2.length>0){
quickSort(a2,0,a2.length-1);;
}
}
public static void main(String[] args){
int a[] = {49,38,65,97,76};
quick(a);
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
}
}
最佳情况:O(nlogn)
最坏情况:O(n^2)
平均时间复杂度:O(nlogn)
空间复杂度:O(nlogn)
不稳定排序算法
基本思想:归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,
即把待排序序列分为若干个子序列,每个子序列是有序的。然后把子序列合并成整体有序序列。
import java.util.*;
public class Test {
public static void sort(int[] data,int left,int right){
if(left<right){
int center=(left+right)/2;
sort(data,left,center);
sort(data, center+1, right);
merge(data,left,center,right);
}
}
public static void merge(int[] data,int left,int center,int right){
int [] tmpArr=new int[data.length];
int mid=center+1;
int third=left;
int tmp=left;
while(left<=center&&mid<=right){
if(data[left]<=data[mid]){
tmpArr[third++]=data[left++];
}
else{
tmpArr[third++]=data[mid++];
}
}
while(mid<=right){
tmpArr[third++]=data[mid++];
}
while(left<=center){
tmpArr[third++]=data[left++];
}
while(tmp<=right){
data[tmp]=tmpArr[tmp++];
}
System.out.println(Arrays.toString(data));
}
public static void main(String[] args){
int a[] = {49,38,65,97,76};
sort(a,0,a.length-1);
for(int i=0;i<a.length;i++)
System.out.println(a[i]);
}
}
最佳情况:O(n)
最坏情况:O(nlogn)
平均时间复杂度:O(nlogn)
空间复杂度:O(n)
稳定排序算法
基本思想:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。
import java.util.*;
public class Test {
public static void main(String[] args){
int a[] = {49,38,65,97,76};
sort(a);
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
}
public static void sort(int[] array){
int max=array[0];
for(int i=1;i<array.length;i++){
if(array[i]>max){
max=array[i];
}
}
int time=0;
while(max>0){
max/=10;
time++;
}
List<ArrayList>queue=new ArrayList<ArrayList>();
for(int i=0;i<10;i++){
ArrayList<Integer>queue1=new ArrayList<Integer>();
queue.add(queue1);
}
for(int i=0;i<time;i++){
for(int j=0;j<array.length;j++){
int x= array[j]%(int)Math.pow(10, i+1)/(int)Math.pow(10, i);
ArrayList<Integer>queue2=queue.get(x);
queue2.add(array[j]);
queue.set(x,queue2);
}
int count=0;
for(int k=0;k<10;k++){
while(queue.get(k).size()>0){
ArrayList<Integer>queue3=queue.get(k);
array[count]=queue3.get(0);
queue3.remove(0);
count++;
}
}
}
}
}
最佳情况:O(n*k)
最坏情况:O(n*k)
平均时间复杂度:O(n*k)
空间复杂度:O(n)
稳定排序算法