表、栈和队列基础

一、表

  表有简单数组实现和链表实现。

  对比某些操作的算法时间复杂度:

    1、查询

      1.1 如果查询的参数是对象的下标i,那么数组的时间复杂度为常数时间O(1),单链表为O(i),双链表因为可以从头部或结尾开始查询,所以最坏的情况为i=N/2(N为表的大小),时间复杂度O(N/2)。

      1.2 如果查询的参数是对象本身,那么数组的时间复杂度为O(i),单链表为O(i),双链表为O(i)。它们都需要从头到尾来遍历。

    2、更新

        对于数组的更新代价是昂贵的,因为每次插入一个对象,都需要把该对象后面的所有对象向后移一位,最坏的情况是在顶端插入,时间复杂度就是O(N)。而链表因为只需要改变插入位置前后两个对象的标识,所以花费的时间是查找这个位置的时间,单链表为O(i),双链表最坏情况是O(N/2)。

    小结:

       一般情况下,数组查询速度快,更新速度慢。链表查询速度比数组慢,但更新比数组快。另外由于数组是固定容量的,所以每次对它进行扩容都需要创建一个新的大数组,再把旧数组的值拷贝过去,所以实际使用中要根据需求设置好初始容量和容量因子,过多的扩容会对性能有不少的影响。

      

 二、栈

  栈是遵循先进后出原则的表结构,插入和删除都只能在表的末端进行,这个位置也叫做栈顶。在栈的许多应用中,列出三个实例,深刻说明程序是如何组织的。

  1、平衡符号

    例如编辑器检查某些字符是否配对,如[]、()、{}等,序列[{}]是合法,序列[{]}是不合法的。这个简单的算法用到一个栈:首先建立一个空栈,然后对字符串逐个字符读取,对于除配对符号外的字符忽略。如果读到左配对符,则进栈,如果读到右配对符,则弹出栈顶元素,并判断是否与该右配对符相匹配的左配对符,如果不是,则报错。

  2、后缀表达式

    我们平常使用的是中缀表达式,如a+b*c,转换为后缀表达式为abc*+。转换为后缀表达式的好处是,没有必要知道任何优先的规则。例如计算a+b*c,我们先要记住b*c的结果,然后再和a相加。而计算abc*+,我们只需要按顺序把操作符前面的两个数值执行对应的操作就可以了,例如读到*号,我们就把b和c相乘,得到结果d,现在是ad+,读到+号就把a和d相加。

    这种方法有两个步骤,第一个是把中缀表达式转换为后缀表达式,第二个是执行后缀表达式。

    转换后缀表达式的原理是:建立一个输出栈和操作符栈,然后遵循以下原则:

      2.1、遇到数值放进输出栈
      2.2、遇到操作符,先与操作符栈的栈顶操作符比较优先级,如果栈顶级别高,则把栈顶元素放进输出栈,再比较下一个栈顶,如此循环直到遇到级别小的或空栈,把自己放进操作符栈
      2.3、读完输入串,如果操作符栈还有元素,则逐个弹出到输出栈

      执行后缀表达式的原理是:建立一个输出栈,当见到一个数时就把它推入栈中;在遇到一个运算符时该运算符就作用于从该栈弹出的两个数上,再将得到结果推入栈中。

  3、方法调用

    java的方法栈。

 

三、队列

  像栈一样,队列是遵循先进先出原则的表结构,使用时插入在一端进行而删除则在另一端进行。

 

 

posted on 2013-09-12 17:28  算徒  阅读(470)  评论(0编辑  收藏  举报

导航