Edge插件默认位置在:
C:\Users\AppData\Local\Microsoft\Edge\User Data\Default\Extensions
交换
冒泡排序: O( n 2 n^{2} n2)
// 10个数从小到大排
// 大数不断往后沉
for(i=0;i<9;i++){ //趟数:10-1
for(j=0;j<9-i;j++){ //每趟 在 [0,9-i]之间的元素进行比较, 大数不断下沉
if(a[j]>a[j+1]){
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
快速排序
void qSort(int a[] ,int left, int right){
if(left<right){
int temp=a[left];
int i=left,j=right; // 初始化 i j 指向
while(i<j){
while(i<j&&a[j]>=temp)j--; // 找 比 temp 小的元素, 找到之后 j 保持不动。将值给到 i 位置处。
a[i]=a[j];
while(i<j&&a[i]<=temp)i++;
a[j]=a[i];
}
a[i]=temp;
qSort(a,left,i-1);
qSort(a,i+1,right);
}
}
选择排序: O( n 2 n^{2} n2)
//选择排序,从大到小排
for(i=0;i<9;i++){
k=i;
for(j=i+1;j<10;j++){ //第一轮,找出10个中最大的
if(a[j]>a[k]){ //第二轮,找出后面9个中最大的
k=j; //第三轮, ...
}
}
if(k!=i){
t=a[i];a[i]=a[k];a[k]=t;
}
}
直接插入排序: O( n 2 n^{2} n2)
void Insert_sort(ElementType A[],int n){
int i,j;
ElementType Temp;
for(i=1;i<n;i++){ // 从 序号为1 的元素 开始,和前面的元素 进行比较
Temp=A[i];
for(j=i;j>0&&A[j-1]>Temp;j--) // 与前边的元素 进行比较 并后移
A[j]=A[j-1];
A[j]=Temp;
}
}
希尔排序
改进的插入排序,减少了元素的比较,交换次数
void Insert_sort(ElementType A[],int n){
int i,j,gap;
ElementType Temp;
for(gap=n/2;gap>0;gap/=2){ // 增量序列 递减至 1
//
for(i=gap;i<n;i++){ // 从 序号 为 gap 的元素开始
Temp=A[i];
for(j=i;j>gap-1&&A[j-gap]>Temp;j-=gap){ // 和 前面 距离 差 gap 的元素 进行比较
A[j]=A[j-gap];
}
A[j]=Temp;
}
//
}
}
堆排序
void Swap( ElementType *a, ElementType *b ){
ElementType t = *a; *a = *b; *b = t;
}
void PercDown( ElementType A[], int p, int N )
{ // 由于 数据从0开始存储 ,所以左孩子是 2*i+1 , 右孩子是 2*i+2
/* 将N个元素的数组中以A[p]为根的子堆调整为最大堆 */
int Parent, Child;
ElementType X;
X = A[p]; /* 取出根结点存放的值 */
for( Parent=p; (Parent*2+1)<N; Parent=Child ) {
Child = Parent * 2 + 1;
if( (Child!=N-1) && (A[Child]<A[Child+1]) )
Child++; /* Child指向左右子结点的较大者 */
if( X >= A[Child] ) break; /* 找到了合适位置 */
else /* 下滤X */
A[Parent] = A[Child];
}
A[Parent] = X;
}
void HeapSort( ElementType A[], int N )
{ /* 堆排序 */
int i;
for ( i=N/2-1; i>=0; i-- )/* 建立最大堆 */
PercDown( A, i, N );
for ( i=N-1; i>0; i-- ) {
/* 删除最大堆顶 */ // 把最大的数不断移到后面
Swap( &A[0], &A[i] );
PercDown( A, 0, i );
}
}
分配
不需要进行待排序元素之间的比较,但需要事先知道这些元素的一些情况。
桶排序
待排元素的值都位于某个较小的区间范围之内 [0,max)
将相同值的元素 都放在同一个桶里。
void bucket_sort(int arr[],int n,int max){
int *count=new int[max];
int *temp=new int[n]; // 临时数组
for(int i=0;i<n;i++){
temp[i]=arr[i];
}
for(int i=0;i<max;i++){
count[i]=0; // 初始为0
}
for(int i=0;i<n;i++){
count[arr[i]]++; // 统计 arr 中每个元素出现的次数
}
for(int i=1;i<max;i++){
count[i]=count[i-1]+count[i]; // 统计 该元素前面有多少个元素,包括自己
}
for(int i=n-1;i>=0;i--){ // 从尾部开始,保证稳定性(例如 有两个相同的数,排完之后,仍可以保证他们之间的相对顺序和之前一样)
arr[--count[temp[i]]]=temp[i];
}
}
也可以挂起来
const int N=10;
typedef struct nid{
int data;
struct nid *next;
}node;
typedef struct nid * bucket[N];
bucket a; // 桶里的元素是指向 struct nid 的指针
// 值一样的元素挂到一串下
总之就是,将值一样的元素归结到一块儿,而后串在一起,没有发生待排元素之间的比较。
基数排序
假设有N=10个整数,每个整数的值在 0~999 之间,如果用桶排序,就要建一个大小为1000的桶。
对于这样的情况,考虑分为个位,十位,百位依次进行桶排。
void Radix_sort(int arr[],int n,int max,int d){
// n 是数组长度,max是桶的大小,d是待排元素有几个关键码(例如:637,有个位,十位,百位,三个关键码)
// 对于 区间在[0,999] 的一组数据, d就取3。每一位的数都在[0,9]范围内, max就取10
int *count=new int[max];
int *temp=new int [n];
int Radix=1; // 用于取 arr[i]的某一位
for(int i=0;i<d;i++){// 进行 d 轮
for(int k=0;k<n;k++){
temp[k]=arr[k]; //临时数组
}
for(int j=0;j<max;j++){
count[j]=0; // 初始化
}
for(int k=0;k<n;k++){
count[(arr[k]/Radix)%max]++; // 依据某一位上的数字进行统计
}
for(int j=1;j<max;j++){
count[j]=count[j-1]+count[j]; // 做一个累加序列
}
for(int k=n-1;k>=0;k--){
arr[--count[(temp[k]/Radix)%max]]=temp[k];
}
Radix*=max;
}
}
为什么要依次?
对于 (35,43,37,33,36),如果直接按十位进行排序,无论是
从尾部开始:得到 (35,37,33,36,43)
从头部开始:得到 (36,33,37,35,43)
可见,对于十位数值一样的一组数来说,他们的内部依然不是有序的,结果都是不对的。
而如果先进行个位的排序,得到:尾部开始(43,33,35,36,37)/ 头部开始(33,43,35,36,37),此时,个位就是有序的
然后再进行按十位的排序(从尾部开始),得到(33,35,36,37,43)
从尾部开始有何意义?
排完序之后,相对顺序不会改变。
对于上面的个位排序,之前,43本就是在33前面,从尾部开始可以保证这点不会改变
对于上面的十位排序,之前,个位排序之后得到的(33,35,36,37),如果十位排序是从尾部开始,就可以保证这个相对顺序。否则,如果是从头部开始,就会得到(37,36,35,33)