线性表的两种存储结构:顺序存储存储密度大,逻辑上相邻元素在物理上也是相邻的,不方便插入和查找操作。
环形队列:逻辑上把数组看成环形的,解决了“假溢出现象”。
栈:编译器管理,向低地址拓展的数据结构,是一块连续的内存空间。
堆:程序员管理,向高地址拓展的数据结构,是不连续的内存空间。
尾递归:核心就是通过参数传递结构,达到不压栈的目的。尾递归函数的特点是在回归过程中不用做任何操作。
当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建一个新的。
补充:当C程序中调用了一个函数时,栈中会分配一块空间来保存与这个调用相关的信息,每一个调用都被当作是活跃的。栈上的那块存储空间称为活跃记录或者栈帧。
栈帧由5个区域组成:输入参数、返回值空间、计算表达式时用到的临时存储空间、函数调用时保存的状态信息以及输出参数。
当你用的函数是尾递归的时候,比如下面这个程序,如果你把它也存入栈帧里面,你会发现当你回来调用的时候,它不会做什么事情,因为它需要做的事情已经在最开始调用的时候做了。所以后面的调用函数需要的栈帧直接覆盖在上一次的调用的栈帧。
int facttail(int n, int res) { if (n < 0) return 0; else if(n == 0) return 1; else if(n == 1) return res; else return facttail(n - 1, n *res); }
递归:
下面这个递归每次函数调用的返回值都依赖于用n乘以下一次函数调用的返回值,因此每次调用产生的栈帧将不得不保存在栈上直到下一个子调用的返回值确定。
int fact(int n) { if (n < 0) return 0; else if(n == 0 || n == 1) return 1; else return n * fact(n - 1); }
所以递归和为尾递归效率差很多。