这个快排的话,说实话,之前一直写的都是递归形式的快排,对待非递归的快排,也就是自己要维护一个栈,所以觉得挺有意义的,单开一个博文,记录一下。
先把我之前的递归形式的快排放上来,当然这个也是做了优化的快排,并没有每一次都把轴心元素和找到的元素交换,而是先通过low和high所指的元素之间的相互赋值,从而找到轴心元素应该所在的位置,从而直接一个赋值即可。
具体的步骤如下:
这里的话,将a[low]看作轴心元素,先用一个临时变量tmp保存数组a[low]的值,然后,从high侧开始比较,如果比tmp大,就移动high的指针,如果小的话,直接将这个值赋给low指针所指的值,low指针所指的第一个值是咱们的轴心元素,所以不用担心值的覆盖问题的。同样,low那边的元素也是同样的道理。代码如下:
#include<stdio.h>
//先写一个递归的快排算法
void printArray(int a[],int n);
int partition(int arr[],int low,int high)
{
printf("%d %d\n", low,high);
int aim;
aim = arr[low];
while(low < high)
{
while(low < high && arr[high] >= aim) --high; //先从high开始
//直到while不满足循环的时候,即存在一个比中间值小的数,此时赋值过来,这里不用交换
arr[low] = arr[high];
while(low < high && arr[low] <= aim) ++low;
arr[high] = arr[low];
}
arr[low] = aim;
return low;
}
void QSort(int arr[],int low,int high)
{
if(low < high)
{
int middle;
middle = partition(arr,low,high);
printf("middle = %d\n",middle );
QSort(arr,low,middle - 1);
QSort(arr,middle + 1,high);
}
}
void quicksort_firstq(int arr[],int n)
{
QSort(arr,0,n-1);
}
void printArray(int a[],int n)
{
int i;
for(i = 0;i < n ; i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
int main(int argc, char const *argv[])
{
int a[8]={8,3,6,2,9,5,1,4};
quicksort_firstq(a,8);
printArray(a,8);
return 0;
}
但是这道题目确是要求用非递归的方法,有点意思哦~
题目如下:
(1)
#include<stdio.h>
#define FALSE 0
#define TRUE 1
typedef struct
{
int low;
int high;
}SNode;
int partition(int arr[],int low,int high)
{
int aim;
aim = arr[low];
while(low < high)
{
while(low < high && arr[high] >= aim) --high; //先从high开始
//直到while不满足循环的时候,即存在一个比中间值小的数,此时赋值过来,这里不用交换
arr[low] = arr[high];
while(low < high && arr[low] <= aim) ++low;
arr[high] = arr[low];
}
arr[low] = aim;
return low;
}
void quicksort1(int arr[],int low,int high)
{
int tag; //判断序列是否有序
int position; //轴心元素应该处的位置
int lnum,rnum; //左右子序列中元素的个数
int count; //栈中元素的个数
SNode Stack[100]; //栈 0位置不用
tag = TRUE;
count = 0;
while(tag)
{
position = partition(arr,low,high);
if(position == low) //这里要判断是否是一个元素,如果是一个元素则有序,否则就需要进一步排序
{
if( (high-low) == 0)
tag = FALSE;
else
low = low + 1;
}
if(tag)
{
lnum = position - low;
rnum = high - position;
if( lnum > 1 || rnum > 1)
{
count++;
if(lnum <= rnum) //左边的少,则先排左边的,将右边的上下界入栈
{
Stack[count].low = position+1;
Stack[count].high = high;
high = position - 1;
}
else
{
Stack[count].low = low;
Stack[count].high = position - 1;
low = position + 1; //先排右边的
}
}//if( lnum > 1 || rnum > 1)
}//if(tag)
if(!tag || (lnum <= 1 && rnum <= 1)) //已经有序的时候
{
if(count)
{
low = Stack[count].low; //将栈中保存的上下界弹出
high = Stack[count].high;
count --; //出栈
tag = TRUE; //设定此时栈中无序
}//if
}//if
}//while
}
void quicksort_1(int arr[],int n)
{
quicksort1(arr,0,n-1);
}
void printArray(int a[],int n)
{
int i;
for(i = 0;i < n ; i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
int main(int argc, char const *argv[])
{
int a[8]={7,3,6,2,9,5,1,4};
quicksort_1(a,8);
printArray(a,8);
return 0;
}
(2)
第二问,我们在排序之前先进行元素个数的检查
#include<stdio.h>
#define FALSE 0
#define TRUE 1
void printArray(int a[],int n);
//这样写并没有让记录小于3时用比较排序
typedef struct
{
int low;
int high;
}SNode;
void swap(int *i,int *j)
{
int p;
p = *i;
*i = *j;
*j = p;
}
int partition(int arr[],int low,int high)
{
int aim;
aim = arr[low];
while(low < high)
{
while(low < high && arr[high] >= aim) --high; //先从high开始
//直到while不满足循环的时候,即存在一个比中间值小的数,此时赋值过来,这里不用交换
arr[low] = arr[high];
while(low < high && arr[low] <= aim) ++low;
arr[high] = arr[low];
}
arr[low] = aim;
return low;
}
//这里我理解为冒泡排序吧
void compareSort(int arr[],int low,int high)
{
int remark;
int num = high - low + 1;
do
{
remark = FALSE;
for(int i = low; i < num - 1 ; i++)
{
if( arr[i] > arr[i+1] )
{
swap( &arr[i] , &arr[i+1] );
remark = TRUE;
}
}
num -- ;
}while(remark);
}
void __quicksort2(int arr[],int low,int high)
{
int tag = TRUE; //判断序列是否有序
SNode Stack[100];
int lnum,rnum;
int position;
int i,j;
int count = 0; //记录栈中元素,要初始一下元素
while(1)//这里不是tag了
{
//先判断待排记录
if(high - low + 1 <= 3)
{
compareSort(arr,low,high);
//先判断栈里是否有元素,有就弹出
if(count)
{
low = Stack[count].low;
high = Stack[count].high;
count --;
}
else
break;
}
else
{
position = partition(arr,low,high);
lnum = position - low;
rnum = high - position;
count++;
if( lnum <= rnum ) //左边的元素少,右边入栈
{
Stack[count].low = position + 1;
Stack[count].high = high;
high = position - 1;
}
else
{
Stack[count].low = low;
Stack[count].high = position - 1;
low = position + 1;
}
}
}
}
void quicksort2(int arr[],int n)
{
__quicksort2(arr,0,n-1);
}
void printArray(int a[],int n)
{
int i;
for(i = 0;i < n ; i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
int main(int argc, char const *argv[])
{
int a[8]={7,3,6,2,9,5,1,4};
quicksort2(a,8);
printArray(a,8);
return 0;
}