这儿是我的笔记,希望大家可以友好交流!!谢谢#__#
这一篇就记录两个都运用分治思想的排序算法,快速排序和归并排序。
(一)快速排序:
内部排序无非用插入排序,希尔排序,快速排序,大容量的输入推荐使用希尔排序和快速排序,数量小的插入排序更合适,当然为了一下就能写好,用冒泡和选择排序也可以(哈哈哈)。快排的平均复杂度是O(NlogN),是几大排序中最快的。
基本算法:
1:如果S中的元素是0和1,则返回
2:取s中的任一元素作为枢纽元
3:将S-{V}分成2个不相交集合,S1= {x属于S-{V}|x
void Quick_Sort(int *A,int N)
{
if(A==NULL || N <= 0)
{
printf("输入数组有误\n");
exit(0);
}
Quick(A,0,N-1);
}
三数中值,并返回枢纽元
int Medium_WithThree(int* A,int left,int right)
{
int center = (left + right) >> 1;
if(A[left] > A[right])
Swap(A,left,right);
if(A[left] > A[center])
Swap(A,left,center);
if(A[center] > A[right])
Swap(A,center,right);
/**以上三步其实已经A[left] < A[center] < A[right],接下来再把中值放到倒数第二个*/
Swap(A,center,right-1);
return A[right-1];
}
void Swap(int *A ,int a,int b)
{
int tmp ;
tmp = A[a];
A[a] = A[b];
A[b] = tmp;
}
void Quick(int *A,int left,int right)
{
int shuniu = 0;
int i =0, j =0;
if(right - left >= 3)//有三个元素时以上时采用快排,界限一般定位10,因为10以下用插入比较合适,不知道为什么只有3才很合适
{
shuniu = Medium_WithThree(A,left,right);
i = left; j = right-1;
//j这是中枢的位置用于和i换,Swap(A,i,right-1),所以不参与中途交换;
while(1)
{
while(A[++i] < shuniu){}
while(A[--j] > shuniu){}
if(i < j)
{
Swap(A,i,j);
}
else
break;
}
Swap(A,i,right-1);
Quick(A,left,i-1);
Quick(A,i+1,right);
}
else
{
Insert_Sort(A,left,right);
}
}
注意上面一定要让++i,–j,否则当遇到和枢纽元相等时,程序就进入死循环了。
(二)归并排序
归并排序,平均复杂度也是O(NlogN),但是由于合并2个表时需要附加的内存,还要花费时间将数据拷贝到临时数组,再拷贝回去,所以一般采用快排不用归并但是归并的是外部排序的基础思想。
驱动例程:提前分配好数组,避免每次递归都要malloc
void Merge_Sort(int *A,int N)
{
int* tmp = NULL;
if(N < 0 || A == NULL)
{
printf("数组不合法\n");
return ;
}
else
{
tmp = (int*)malloc(sizeof(int)*N);
if(tmp!=NULL)
{
Merge(A,tmp,0,N-1);
free(tmp);
}
}
}
实际的递归函数
void Merge(int *A,int* tmp,int left,int right)
{
int center;
if(left < right)
{
center = (right+left) / 2;
Merge(A,tmp,left,center);
Merge(A,tmp,center+1,right);
Merge1(A,tmp,left,center,right);
}
}
合并函数:注意这里的tmppos一定要从left开始,不能从0开始
void Merge1(int* A,int* tmp,int left,int leftend,int rightend)
{
int right = leftend+1;
/**这里的tmp一定不能用0表示*/
int tmppos = left;
while(left <=leftend && right <= rightend )
{
if(A[left] < A[right])
tmp[tmppos++] = A[left++];
else
tmp[tmppos++] = A[right++];
}
while(left<=leftend)
{
tmp[tmppos++] = A[left++];
}
while(right<=rightend)
{
tmp[tmppos++] = A[right++];
}
while(--tmppos>=0)
{
A[tmppos] = tmp[tmppos];
}
}
两个运用了分治思想的也好了。