(排升序)总体思路
- 1.先从数据中取出一个数作为基准数。
- 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边(单趟排序)。
- 3.再对左右区间重复第二步,直到各区间只有一个数。
(排升序)n为数据数量 细分思路
假设我们选了最前面的数据为基数(key)
- 创建两个变量left和right,left是最前面的数的下标,right是最后面的那个数下标
- 再让left和right分别往前面走,这里由于选的是最前面的为key,那么这里要让right先走
- right往前走,去找比key小的数,找到后,right暂停往前走
- 再让left往前面走,去找到比key大的数,找到后,left暂停往前走
- 那么此时就让 left 和 right 的下标所对应数据,进行交换.
- 交换往后,再让left和right重复上述操作
- 当 left 和right 相遇时,本次单趟排序结束,并记录下此刻相遇的位置下标为m
- 然后我们将区间分为 [0,m-1] [m+1,n-1] ,在对两个区间分别进行单趟排序
- 我们再对两个区间进行一次划分,划分好后,又重复一次单趟排序
- 再重复分区,单趟排序操作,直到各区间只有一个元素时,就结束了快排
问题一:这是为了防止 出现两者相遇处的数值比key还大
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
int PartSort(int* a, int left, int right)//单趟排序
//1.先从数列中取出一个数作为基准数。
//2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
{
int key = a[left];
int keyindex = left;
while (left < right)
{
//这里要保证left= key)//找小
{
--right;
}
while (left < right && a[left] <= key)//找大
{
++left;
}
Swap(&a[left], &a[right]);
}
swap(&a[keyindex], &a[left]);//&a[right]
return left;//return right;
}
void QuickSort1(int* a, int left, int right)
{
assert(a);
if (left > right)
{
return;
}
int div = PartSort(a, left, right);
//3.再对左右区间重复第二步,直到各区间只有一个数。
QuickSort(a, left, div - 1);
QuickSort(a, div + 1, right);
}
- 先在数据里找一个数据,将其确定为坑位(key),这里将最后面的位置作为坑位,
- 创建好两个变量begin,end,这两个变量是用来存数据的下标
- 将数值key的下标赋给begin,再将最后位置的下标赋给end,
- begin往前去找比key大的数据,如果没有找到,那么就往前面去找
- 找到后,那么begin就暂停往前,并且交换keybegin的数据
- 此时begin的位置就是新的坑位,此刻begin前面的数小于key
- 再让end往前去找比key小的,找到就交换,一次排序结束
- 不断重复上述操作,直到,两者相遇,就结束并返回现在相遇的位置下标 m,
- 此刻m位置前面的数据小于key,m后面的>=key
- 然后在对数据进行分区 [0,m-1] m [m+1,n-1]
- 然后,在对区间 [0,m-1] [m+1,n-1]进行上面相同的操作
- 不断的分区,再排序。直到区间里只有一个数据时,就完成快排
//方法2:挖坑法 排升序
void PartSort2(int* a, int left, int right)
{
assert(a);
int key = a[right];//此时right是一个坑
while (left < right)
{
while (left < right && a[left] <= key)
//找大
{
++left;
}
a[right] = a[left];//填坑,此时也创建了新的坑left
while (left < right && a[right] >= key)
//找小
{
--right;
}
a[left] = a[right];//在填坑,在创建新坑right
}
a[left] = key;//a[right]=key;
return left;//return right;
}
void QuickSort2(int* a, int left, int right)
{
assert(a);
if (left > right)
{
return;
}
int div = PartSort2(a, left, right);
//3.再对左右区间重复第二步,直到各区间只有一个数。
QuickSort2(a, left, div - 1);
QuickSort2(a, div + 1, right);
}
前提:初始的begin是最前面位置的下标,end是最后一个位置的下标
- 先在数据里找到一个基数(key)
- 再创建两个变量 prev cur,prev=begin-1 cur=begin
- 让cur去找比key小的数,找到了,那么cur就不暂停往前,如果比key大,就继续往前面走
- 然后++prev,再去交换prev对应的数据和cur对应的数据
- 再继续重复上面操作,直到cur遍历完整个数据,那么再++prev
- 交换prev和key所对应的数据,并返回此时prev位置的下标m,该单趟排序结束
- 再对区间 [0,m-1] [m+1,n-1](n为数据数目)进行上述操作
- 当区间被划分为只有一个元素是就完成了快排
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
//前后指针方法 排升序
int PartSort3(int* a, int begin, int end)
{
int prev = begin - 1;
int cur = begin;
int keyindex = end;
while (cur <= end)
{
if (a[cur] < a[keyindex] && ++prev != cur)//找小
{
Swap(&a[cur], &a[prev]);
}
++cur;
}
Swap(&a[++prev], &a[keyindex);
return prev;
}
void QuickSort3(int* a, int left, int right)
{
assert(a);
if (left > right)
{
return;
}
int div = PartSort3(a, left, right);
QuickSort3(a, left, div - 1);
QuickSort3(a, div + 1, right);
}
该算法是采用分治法 (Divide and Conquer)的一个非常典型的应用。
将已有序的子序列合并,得到完全有序的序列
即先使每个子序列有序,再使子序列段间有序。
若将两个有序表合并成一个有序表,称为二路归并。
n是数数组里数据数目 排升序
- 先malloc一个大小为n的整型数组tmp
- 将数组进行划分区间,begin=0 end=n-1 mid=(begin+end)/2 [begin ,mid] [mid+1 ,end]
- 然后继续对这两个区间继续划分,得到4个区间
- 再不断重复分区操作,当每个区间只有一个数据时,分区结束,并开始返回,不在往下分
- 然后在不断比较两区间的数,将它们从小往大依次放入tmp数组里
- 当有一个区间已全部完成,那么在将未完成的剩下区间拷贝到tmp的后面位置处
- 最后将数组tmp拷贝给原数组
void _MergeSort(int* a,int* tmp, int left, int right)
{
int mid = (left + right) / 2;
_MergeSort(a, tmp, left, mid);
_MergeSort(a, tmp, mid+1, right);
int begin1 = left, end1 = mid;
int begin2 = mid + 1, end2 = right;
int index = begin1;//记录下标
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] <= a[begin2])
{
tmp[index++] = a[begin1++];
}
else if(a[begin1]>a[begin2])
{
tmp[index++] = a[begin2++];
}
}
while (begin1 < end1)
tmp[index++] = a[begin1++];
while (begin2 < end2)
tmp[index++] = a[begin2++];
for (int i = left; i <= right; i++)
{
a[i] = tmp[i];
}
}
void MergeSort(int* a, int n)
{
assert(a);
int* tmp = (int*)malloc(sizeof(int) * n);
_MergeSort(a, tmp, 0, n - 1);
feee(tmp)
}