目录
有递归和非递归两种方式,经常考代码。一定要理解、会背代码、会敲代码。
非递归
过程:
第一遍:按照自己的理解整出代码。
冒泡排序遇到的问题:
1、冒泡排序的函数名称叫什么呢?bubble:气泡的意思。所以叫Bubblesort。
2、思想有了,但是脑子里浮现的大致步骤和课本上的不大一样。
3、没有想过,怎样才是已经有序啦?应该想到使用一个flag来标志一下的。
快速排序遇到的问题:
1、已经忘了快速排序的步骤与做法。
2、有递归和非递归两种方式,但是,看到递归两个字就害怕。两种模式都不会写。
3、快速排序名字:QuickSort
4、while(low<high && a[high] >= pivot){--high;}
我在敲快速排序的代码时,使用的是high >= pivot,但是pivot是一个元素值,不是一个下标,应该用a[high]>=pivot才对。并且,不明白为什么要有low<high????,
我找到答案了:这里的low和high都是下标,防止pivot就是最小的元素,所以一直满足a[high]>= pivot,就会一直--high,然后越界,low< high是防止越界的。
总结一下。要分清下标和元素值。
5、忘了返回low的值,也就是说,我只敲出了一趟的代码,没有想过以后怎么办,只有返回low的值,才能令pivot 重新=low。开始新一轮的循环。
啊,不对,自作多情了。。。这里 return low;是为了后面的 a[low] = pivot;这里a[low] = pivot,是因为排序之后会空出来一个位置,这个位置就是需要填入pivot。
开启新循环是后面调用这个函数的事情。。。
6、注意 partition函数里的形参是(ElemType a[], int low, int high)
7、想不出非递归的方法。
第二遍:忘了不少啊。。。废物
冒泡排序
思想:在每一趟里找出一个最小值(或最大值),安顿好它的位置。接下来在剩余的元素里继续寻找。每次寻找到的元素就会确定它的最终位置。
所采用的比较方式是相邻的两个元素进行比较,若a[j-1]<a[j],则交换位置。那么,在一趟过去后,并不是除了最小值跑到开头的位置外,其他元素相对位置不变,而是只要符合换位置条件就会两两交换,所以每一趟发生的交换次数未知。
//C语言里其实并没有交换这一基本函数,只能自己敲一个。
void swap(int *a,int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
//冒泡排序,本次以选出最小的为例。
void BubbleSort(ElemType a[],int n) //不需要一个特殊的a[0]了,所以,0~n-1.
{
for (int i = 0; i < n-1; i++)
{
flag = false;//表示本趟冒泡排序是否发送交换
for (int j = n-1; j >= i;j--) //一趟冒泡过程
{
if (a[j] < a[j-1])
{
swap(a[j-1],a[j]);//交换
flag = true;
}
}
if(flag == false)
{
return;
/*注意到:在该for循环里,每次都将flag置为false,
若没发生交换,则不会有对flag的赋值为true。
则说明已经有序,排序完毕。
*/
}
}
}
快速排序
思想:选定一个枢轴(一般是首元素)。从两头开始,往中间走,若最后一个小于所选的枢轴值,则换到前面来,放在枢纽所在的位置,那么后面就会空出来一个位置,从枢轴后一个开始选,选出一个大于枢轴的元素放在空出来的位置,那么此时前面又空出来一个,再从后面选一个元素放在空出来的位置…。直到无法交换,把枢轴放在空出来的位置上,此时就形成了枢轴左边的元素都比枢轴小,右边的都比枢轴大。(与枢轴的远近只代表交换的前后顺序,与大小关系不大)。
递归
//划分操作:将比枢轴(pivotpos)小的元素放在枢轴左边,比枢轴大的元素放在枢轴右边。
int Partition(ElemType a[],int low,int high) //一趟划分
{
ElemType pivot = a[low];//将当前表中第一个元素设为枢轴,对表进行划分
while (low<high)//循环跳出条件
{
while (low < high && a[high] >= pivot)
{
--high;
}
a[low]=a[high];//将比枢轴小的元素移动到左端
while (low < high && a[low] <= pivot)
{
++low;
}
a[high] = a[low];//将比枢轴大的元素移动到右端
return low;
}
a[low] = pivot;
}
//快速排序·递归方式。
void QuickSort(ElemType a[],int n)
{
if (low < high) //递归跳出条件
{
int pivotpos = partition (a,low,high);
//partition()就是划分操作,将表a[low...high]划分为满足上述条件的两个子表
QuickSort(a,low,pivotpos-1);
//这里的pivotpos= partition返回的值,也就是枢轴所在的位置,low.
//因为C语言的特性,这里的low 和 partition返回的low是两个low,指向两个不同的地方。
QuickSort(a,pivotpos+1,high);
}
}
非递归
递归的算法主要是在划分子区间,如果要非递归实现快速排序,只要使用一个栈来保存区间就可以了。
一般将递归程序改成非递归首先想到的就是使用栈,因为递归本身就是一个压栈的过程。