归并排序代码及思路:
#include<stdio.h>
const int maxn=1000001;
int A[maxn];
//归并排序的基本思路(子循环过程):将序列分成两半,分别排序,再合并,重复此过程
//从最小的单元合并到最大的单元,排序完成
void merge(int arr[], int left, int middle, int right){//合并函数,借用两个数组实将一个两半分别为有序序列的数组合并为一个有序数组
int i, j;
int n1=middle-left+1, n2=right-middle;//n1和n2分别是左半边和右半边数组的容量
int L[n1], R[n2];//创建两个数组,一个装左半边,一个装右半边
for(i=0;i<n1;i++) L[i]=arr[left+i];//取出左半边数组的值
for(j=0;j<n2;j++) R[j]=arr[middle+1+j];//取出右半边数组的值
i=j=0;
int k=left;//重新填充数组,从左边界left开始
while(i<n1 &&j<n2)//这里条件是且,有一个不符合就退出循环到下一步了
if(L[i]<R[j]) arr[k++]= L[i++];//注意这里的L和R分别等于arr的左半边和右半边,由于是从子过程一步一步调用上来的,已经是有序序列了
else arr[k++]=R[j++]; //在分析问题时,一定要注意每个参量的状态!!!
while(i<n1)arr[k++]=L[i++];//当有一个跑完,另外一个直接跑完即可
while(j<n2)arr[k++]=R[j++];
/* Please fill this part:
merge (L[0],...,L[n1-1]) with (R[0],...,R[n2-1]) and store the result (in sorted order) in arr[left],...,arr[right]. */
//要排序的范围是arr[left],arr[right]
}
void mergesort(int arr[],int left, int right){//实现子循环过程的函数
if(left<right){
int middle=(left+ right)/2;
//add something here. Think it by yourself.
mergesort(arr,left,middle);// 根据归并排序的思路进行状态分析,两个mergesort得到的是两个有序的序列,分别为arr的左半边和右半边
mergesort(arr,middle+1,right);//此时arr的状态是左半边和右半边分别是有序序列
merge(A,left,middle,right);//合并
}
}
int main() {
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d", &A[i]);
mergesort(A,0,n-1); //edit this sentence 涉及到数组注意从0开始
for(int i=0;i<n;i++) printf("%d ", A[i]);
}
快速排序代码及思路:
#include <stdio.h>
#pragma comment(linker, "/STACK:1073741824")
#include<stdlib.h>
const int maxn=1000001;
int A[maxn];
//简述快排的过程:
//选取一个序列的最后一个数作为partition
//j是用来遍历序列的变量,当遍历完时,i是大于partition的第一个数的位置
//k的左边小于k,右边大于k
//再对左右分别进行partition
//直到最小的单元退出子循环
//此时左边只剩一个元素,partition=low,右边也只剩一个元素,partition=high,以此作为判断退出循环的条件
void swap(int &a, int &b) {
int c = a; a = b; b = c;
}
int partition(int arr[], int low, int high) {
swap(arr[low+rand()%(high-low+1)],arr[high]);//将arr[high]设置成随机值,防止针对数据
int pivot = arr[high], i = low;//感觉没什么必要设置pivot变量,后面反而容易写错?
for (int j = low; j < high; j++) {
//add something here
if(arr[j]<=pivot)
swap(arr[i++],arr[j]);//把小于pivot的数放到i的前面
}
swap(arr[i],arr[high]);//add something here,等j遍历完时,交换i与arr[high]
//注意arr[high]不能写成pivot,因为要交换的是数组元素的值,pivot只是一个临时变量,不会改变数组最后一个元素arr[high]的值
return i;//i的值是间隔数在数组中的位置
}
void quickSort(int arr[], int low, int high) {
if (low < high) {
int k = partition(arr, low, high);
if(k!=low)//add something here 前半段退出子循环的条件是k=low,对应的是只剩一个元素的情况
quickSort(arr,low,k-1);//不需要用循环语句,因为函数本来就是循环调用,直接用if即可
if(k!=high)//add something here 后半段退出子循环的条件是k=high,对应的是只剩一个元素的情况
quickSort(arr,k+1,high);
}
}
int main() {
int n;
scanf( "%d", &n);
for (int i=0; i<n; i++) scanf("%d", &A[i]);
quickSort(A,0,n-1); //change this sentence 数组注意边界!
for (int i=0; i<n; i++) printf("%d ", A[i]);
return 0;
}