18从汇编的角度深入理解c++_深入理解二叉树前置(递归和快速排序算法)
递归的本质就是:
自己调用自己(关键是如何自己调用自己)。
求:1,2,3,……100的和,我们知道结果是5050.
正常逻辑:1+2+3+4+……+100.
逆向逻辑:s(100) = s(99) + 100;
s(99) = s(98) + 99;
……………………………
s(1) = 1;
转换为递归:
s(n) = s(n-1) + n
s1 = 1
正常思维就是:横向从左到右加
逆向的递归思维就是:纵向分为s(n-1)和n
递归不好理解主要是:
1、逆向思维
2、解决的问题与问题复杂度无关,只要找到调用关系和出口。
例如:
斐波那契数列1、1、2、3、5、8、13、21、34……
F(n)=F(n - 1)+F(n - 2) //调用关系
F(0)=1,F(1)=1; //出口
#include "stdafx.h"
//1 1 2 3 5 8 13 21
int f(int n){
if(n==1||n==2)
return 1;
else
return f(n-1)+f(n-2);
}
int _tmain(int argc, _TCHAR* argv[])
{
int m=7;
int x = f(m);
printf("f(%d):%d\n",m,x);
getchar();
return 0;
}
调用堆栈:

递归类似于栈的特性:先进后出。
快速排序算法递归实现:
#include "stdafx.h"
//
int partition(int arr[] ,int startIndex,int endIndex){
int pivot = arr[startIndex];
int left = startIndex;
int right = endIndex;
while (left!=right){
//控制right 指针比较并左移
while (left<right&&arr[right]>pivot){
right--;
}
//控制left指针比较并右移
//有等于是因为:int pivot = arr[startIndex]; int left = startIndex;
while (left<right&&arr[left]<=pivot){
left++;
}
//left和right都找到后,交换这俩的值
if (left<right){
int p =arr[left];
arr[left]=arr[right];
arr[right]=p;
}
}
//到这一步的时候left==right了
//执行pivot 和指针重合点交换
arr[startIndex] = arr[left];
arr[left] = pivot;
//至此,依据第一个元素(基准元素pivot),把数组大于第一个元素的放在他右边,小于的放在左边,并返回基准元素(pivot)最终的下标
return left;
}
void quicksort(int aa[],int startIndex,int endIndex)
{
if(startIndex>=endIndex){
return;
}
int p = partition(aa, startIndex, endIndex);
/************************/
quicksort(aa, startIndex, p - 1);
quicksort(aa, p + 1, endIndex);
}
int _tmain(int argc, _TCHAR* argv[])
{
int aa[11]={5,9,3,2,1,7,10,8,6,4,12};
for(int i=0;i<11;i++){
printf("%d ",aa[i]);
}
printf("\n*************\n");
quicksort(aa,0,10);
for(int i=0;i<11;i++){
printf("%d ",aa[i]);
}
getchar();
return 0;
}
快速排序的逻辑是,若要对 nums[startIndex..endIndex] 进行排序,我们先找一个分界点 p,通过交换元素使得 nums[startIndex..p-1] 都小于等于 nums[p],且 nums[p+1..endIndex] 都大于 nums[p],然后递归地去 nums[startIndex..p-1] 和 nums[p+1..endIndex] 中寻找新的分界点,最后整个数组就被排序了。
算法理解示意图如下:


快速排序其实就是个二叉树的前序遍历,归并排序就是个二叉树的后序遍历。

浙公网安备 33010602011771号