这或许是东半球分析十大排序算法最好的一篇文章
十大经典排序算法动画与解析,看我就够了!
临时用的Dev,用到的函数必须先写在前面。
轻松搞定十大排序算法|C++版(上)
轻松搞定十大排序算法|C++版(下)
区别:归并排序是分两块,两块都排好序之后,再将两边排好序的数合再并成一个排序的序列。
1.选定pivot中心轴;
2.将大于pivot的数字放在pivot的右边;
3.将小于pivot的数字放在pivot的左边;
4.分别对左右子序列重复前三步操作。
#include
using namespace std;
int partition(int* arr,int left,int right){
int pivot=arr[left]; //注意
while(left<right){ //注意
while(arr[right]>=pivot && left<right) right--;
arr[left]=arr[right];//这覆盖可以,写swap函数交换也可以,道理是一样的
while(arr[left]<=pivot && left<right) left++;
arr[right]=arr[left];
}
arr[left]=pivot;
return left;
}
//快速排序
void quick_sort(int* arr, int left,int right){
if(left<right){ //注意
int index=partition(arr,left,right);
quick_sort(arr,left,index-1);
quick_sort(arr,index+1,right);
}
}
int main(){
int arr[]={1,1,5,8,3,7,4,1,1};
int size=sizeof(arr)/sizeof(arr[0]); //计算数组大小
quick_sort(arr,0,size-1); //确切下标
for(int i=0;i<size;i++){
//printf("%d",arr[i]);
cout<<arr[i];
}
return 0;
}
/*交换函数
void swap(int* arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
*/
/* 左神的partition函数用从C++改的能跑通
int partition(int* arr, int l, int r) {
int less = l - 1;
int more = r;
while (l < more) {
if (arr[l] < arr[r]) {
swap(arr, ++less, l++);
} else if (arr[l] > arr[r]) {
swap(arr, --more, l);
} else {
l++;
}
}
swap(arr, more, r);
int w[2]={less + 1, more};
return w;
}
*/
我们将本是无序的数组序列,通过两两合并排序之后再合并,最终获得一个有序的数组。
#include
using namespace std;
void merge(int* arr, int l, int m, int r) {//这个函数比快排多个参数,m
int* help = new int[r - l + 1]; //注意新建数组只能只能这样建 int*
int i = 0;
int p1 = l;//指向左侧部分第一个数
int p2 = m + 1;//指向右侧部分第一个数
while (p1 <= m && p2 <= r) { //谁小填谁,相当于个排序
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= m) { //把剩下的追加到后面,如果p1没越界,p2必越界。
help[i++] = arr[p1++];
}
while (p2 <= r) {
help[i++] = arr[p2++];
}
for (i = 0; i < (r-l+1); i++) {
arr[l + i] = help[i]; //注意l+i //把help里的数复制到原数组arr
}
}
//归并排序
void mergeSort(int* arr, int l, int r) {
if (l == r) {//注意这个条件 //只有一个数时
return;
}
int mid = l + ((r - l) >> 1); // (l+r)/2
mergeSort(arr, l, mid); //左部分排好
mergeSort(arr, mid + 1, r);//右部分排好
merge(arr, l, mid, r); //再合并排序
}
int main(){
int arr[]={9,1,5,8,3,7,4,1,1,2};
int size=sizeof(arr)/sizeof(arr[0]);
mergeSort(arr, 0, size-1);
for(int i=0;i<size;i++){
//printf("%d",arr[i]);
cout<<arr[i];
}
return 0;
}
原来的左神的,多了一段。暂时不用。
#include
using namespace std;
void swap(int* arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//归并排序
void merge(int* arr, int l, int m, int r) {
int* help = new int[r - l + 1]; //辅助数组
int i = 0;
int p1 = l;//指向左侧部分第一个数
int p2 = m + 1;//指向右侧部分第一个数
while (p1 <= m && p2 <= r) { //谁小填谁
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= m) { //如果p1没越界,p2必越界
help[i++] = arr[p1++];
}
while (p2 <= r) {
help[i++] = arr[p2++];
}
for (i = 0; i < (r-l+1); i++) {
arr[l + i] = help[i]; //把help里的数复制到原数组arr
}
}
void mergeSort(int* arr, int l, int r) {
if (l == r) {//只有一个数
return;
}
int mid = l + ((r - l) >> 1); // (l+r)/2
mergeSort(arr, l, mid); //左部分排好
mergeSort(arr, mid + 1, r);//右部分排好
merge(arr, l, mid, r);
}
//归并排序
void mergeSort(int* arr, int length) {
if (arr == NULL || length < 2) {
return;
}
mergeSort(arr,0,length - 1);
}
int main(){
int arr[]={9,1,5,8,3,7,4,1,1,2};
int size=sizeof(arr)/sizeof(arr[0]);
mergeSort(arr,size);
for(int i=0;i<size;i++){
//printf("%d",arr[i]);
cout<<arr[i];
}
return 0;
}
介绍大顶堆、小顶堆
那个二叉树只是为计算而想象成的一颗二叉树。
1.让一个数组变成大根堆(并不是有序),第一步就把大顶推建立好,
建立好的大顶推像上图一样。
2.建立好大根堆之后,堆顶位置为整个数组最大值,让它和最后位置交换,,
换完之后,最大值来到了数组最后位置;
3.此时,最后位置为最大值,不动了,让堆大小减一;剩下的做heapify处理
4.每次搞定一个末尾的值
#include
using namespace std;
void swap(int* arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//向上走。
//第一步先整体建立起一个大顶推,后面才好说。。建立大根堆过程(无序的)
void heapInsert(int* arr, int index) {
while (arr[index] > arr[(index - 1) / 2]) {//如果比当前父节点位置大,就和父位置交换
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;// index往上跑,一直往上跑
}
}
//向下走。
//其中有一个值变小,往下沉的过程,重新变成大根堆
//size为最右的边界,size是取不到的
void heapify(int* arr, int index, int size) {
int left = index * 2 + 1;
//下面2句的意思是找到三者之间最大的(根/左/右)
while (left < size) { //注意while只判断left
int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;//选出左右孩子中较大的那个
largest = arr[largest] > arr[index] ? largest : index;
if (largest == index) {
break;
}
swap(arr, largest, index);
index = largest;
left = index * 2 + 1;
}
}
//堆排序
void heapSort(int* arr, int size) {
if (arr == NULL || size< 2) {
return;
}
for (int i = 0; i < size; i++) {//建立大顶推的过程
heapInsert(arr, i);//循环发生完之后,整个数组就变成大根堆了
}
swap(arr, 0, size-1);//建立好大根堆之后,堆顶位置为整个数组最大值,让它和最后位置交换,,换完之后,最大值来到了数组最后位置
size--;
while (size > 0) {
heapify(arr, 0, size);
swap(arr, 0, size-1);//循环操作上述过程
size--;
}
}
int main(){
int arr[]={9,1,5,8,3,7,4,1,1,2};
int size=sizeof(arr)/sizeof(arr[0]);
heapSort(arr,size);
for(int i=0;i<size;i++){
//printf("%d",arr[i]);
cout<<arr[i];
}
return 0;
}
下面这个暂时不用。。之前 heapSort 函数的最后一点是这么写的,不好理解,所以换成了上面那种。其实是一样的,只不过浓缩了。
//堆排序
void heapSort(int* arr, int length) {
if (arr == NULL || length < 2) {
return;
}
for (int i = 0; i < length; i++) {
heapInsert(arr, i);//循环发生完之后,整个数组就变成大根堆了
}
int size = length;
//我说的就是下面这点。。。
swap(arr, 0, --size);//建立好大根堆之后,堆顶位置为整个数组最大值,让它和最后位置交换,,换完之后,最大值来到了数组最后位置
while (size > 0) {
heapify(arr, 0, size);
swap(arr, 0, --size);//循环操作上述过程
}
}
#include
using namespace std;
void swap(int* arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//冒泡排序
void bubbleSort(int* arr, int size){
if (arr == NULL || size < 2) {
return;
}
for (int e = size - 1; e > 0; e--) {//e先指向最后一个数
for (int i = 0; i < e; i++) { //从0至倒数第二个数
if (arr[i] > arr[i + 1]) {
swap(arr, i, i + 1);
}
}
}
}
int main(){
int arr[]={9,1,5,8,3,7,4,1,1,2};
int size=sizeof(arr)/sizeof(arr[0]);
bubbleSort(arr,size);
for(int i=0;i<size;i++){
//printf("%d",arr[i]);
cout<<arr[i];
}
return 0;
}
如果发现在某一趟排序的过程中,数组已经排序了,此时不用再继续排序。
避免了因有序情况下的无意义循环判断。
比如在第三趟,发现已经有序了,并没有执行交换操作,所以flag为true,跳出循环。
//冒泡排序优化
void bubbleSort(int* arr, int size){
if (arr == NULL || size < 2) {
return;
}
for (int e = size - 1; e > 0; e--) { //有这么多趟
bool flag = true; //设置标记
for (int i = 0; i < e; i++) {//开始交换
if (arr[i] > arr[i + 1]) {
swap(arr, i, i + 1);
flag =false;//如果有交换 ,就设为false,一旦没有交换,还是true不变
}
}
if(flag) break;
}
}
#include
using namespace std;
void swap(int* arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//选择排序
void selectionSort(int* arr, int length) {
if (arr == NULL || length < 2) {
return;
}
for (int i = 0; i < length - 1; i++) { //0~倒数第二个
int minIndex = i;
for (int j = i + 1; j < length; j++) { //从i+1直到最后去选择一个最小的,然后交换
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
}
swap(arr, i, minIndex);
}
}
int main(){
int arr[]={9,1,5,8,3,7,4,1,1,2};
int size=sizeof(arr)/sizeof(arr[0]);
selectionSort(arr,size);
for(int i=0;i<size;i++){
//printf("%d",arr[i]);
cout<<arr[i];
}
return 0;
}
将一个记录插入到已经排好序的有序序列中,从而得到一个新的、记录数增1的有序表。
#include
using namespace std;
void swap(int* arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//插入排序
void insertionSort(int* arr, int length) {
if (arr == NULL || length < 2) {
return;
}
for (int i = 1; i < length; i++) {//0位置不用管,从第1位置到最后一个位置都要去比较
for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
swap(arr, j, j + 1);
}
}
}
int main(){
int arr[]={9,1,5,8,3,7,4,1,1,2};
int size=sizeof(arr)/sizeof(arr[0]);
insertionSort(arr,size);
for(int i=0;i<size;i++){
//printf("%d",arr[i]);
cout<<arr[i];
}
return 0;
}
package basic_class_01;
import java.util.Arrays;
public class Code_00_BubbleSort {
public static void bubbleSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int e = arr.length - 1; e > 0; e--) {
for (int i = 0; i < e; i++) {
if (arr[i] > arr[i + 1]) {
swap(arr, i, i + 1);
}
}
}
}
public static void swap(int[] arr, int i, int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
// for test
public static void comparator(int[] arr) {
Arrays.sort(arr);
}
// for test
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
// for test
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
// for test
public static boolean isEqual(int[] arr1, int[] arr2) {
if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
return false;
}
if (arr1 == null && arr2 == null) {
return true;
}
if (arr1.length != arr2.length) {
return false;
}
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
// for test
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// for test
public static void main(String[] args) {
int testTime = 500000;
int maxSize = 100;
int maxValue = 100;
boolean succeed = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
bubbleSort(arr1);
comparator(arr2);
if (!isEqual(arr1, arr2)) {
succeed = false;
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");
int[] arr = generateRandomArray(maxSize, maxValue);
printArray(arr);
bubbleSort(arr);
printArray(arr);
}
}
package basic_class_01;
import java.util.Arrays;
public class Code_02_SelectionSort {
public static void selectionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
}
swap(arr, i, minIndex);
}
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
package basic_class_01;
import java.util.Arrays;
public class Code_01_InsertionSort {
public static void insertionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 1; i < arr.length; i++) {//0位置不用管,从第1位置到最后一个位置都要去比较
for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
swap(arr, j, j + 1);
}
}
}
public static void swap(int[] arr, int i, int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
package basic_class_01;
import java.util.Arrays;
public class Code_03_HeapSort {
1.让一个数组变成大根堆(并不是有序)
2.建立好大根堆之后,堆顶位置为整个数组最大值,让它和最后位置交换,,换完之后,最大值来到了数组最后位置;
3.此时,最后位置为最大值,不动了,让堆大小减一;剩下的做heapify处理
4.每次搞定一个末尾的值
public static void heapSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 0; i < arr.length; i++) {
heapInsert(arr, i);//循环发生完之后,整个数组就变成大根堆了
}
int size = arr.length;
swap(arr, 0, --size);//建立好大根堆之后,堆顶位置为整个数组最大值,让它和最后位置交换,,换完之后,最大值来到了数组最后位置
while (size > 0) {
heapify(arr, 0, size);
swap(arr, 0, --size);//循环操作上述过程
}
}
//建立大根堆过程(无序的)
public static void heapInsert(int[] arr, int index) {
while (arr[index] > arr[(index - 1) / 2]) {//如果比当前父节点位置大,就和父位置交换
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;// index往上跑
}
}
//其中有一个值变小,往下沉的过程,重新变成大根堆
public static void heapify(int[] arr, int index, int size) {
int left = index * 2 + 1;
while (left < size) {
int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;//选出左右孩子中较大的那个
largest = arr[largest] > arr[index] ? largest : index;
if (largest == index) {
break;
}
swap(arr, largest, index);
index = largest;
left = index * 2 + 1;
}
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
package basic_class_01;
import java.util.Arrays;
public class Code_05_MergeSort {
public static void mergeSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
mergeSort(arr, 0, arr.length - 1);
}
public static void mergeSort(int[] arr, int l, int r) {
if (l == r) {//只有一个数
return;
}
int mid = l + ((r - l) >> 1); // (l+r)/2
mergeSort(arr, l, mid); //左部分排好
mergeSort(arr, mid + 1, r);//右部分排好
merge(arr, l, mid, r);
}
public static void merge(int[] arr, int l, int m, int r) {
int[] help = new int[r - l + 1]; //辅助数组
int i = 0;
int p1 = l;//指向左侧部分第一个数
int p2 = m + 1;//指向右侧部分第一个数
while (p1 <= m && p2 <= r) { //谁小填谁
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= m) { //如果p1没越界,p2必越界
help[i++] = arr[p1++];
}
while (p2 <= r) {
help[i++] = arr[p2++];
}
for (i = 0; i < help.length; i++) {
arr[l + i] = help[i]; //把help里的数复制到原数组arr
}
}
}
package basic_class_01;
import java.util.Arrays;
public class Code_04_QuickSort {
public static void quickSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
quickSort(arr, 0, arr.length - 1);
}
public static void quickSort(int[] arr, int l, int r) {
if (l < r) {
//swap(arr, l + (int) (Math.random() * (r - l + 1)), r); //随机快排
int[] p = partition(arr, l, r);
quickSort(arr, l, p[0] - 1);
quickSort(arr, p[1] + 1, r);
}
}
public static int[] partition(int[] arr, int l, int r) {
int less = l - 1;
int more = r;
while (l < more) {
if (arr[l] < arr[r]) {
swap(arr, ++less, l++);
} else if (arr[l] > arr[r]) {
swap(arr, --more, l);
} else {
l++;
}
}
swap(arr, more, r);
return new int[] { less + 1, more };
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}