如果知道堆栈大小良好的上限,使用了O一个数组(如另一个答案中概述的)可能是一个合理的事情。所有六个操作都是O(1),并且如果堆栈经常在最大尺寸附近运行,则每个元素的存储量是最佳的。另一方面,如果您不知道堆栈大小的上限,或者堆栈大小通常与上限相比较小,则使用双向链表,如下所述。另一方面,如果您不知道堆栈大小的上限,或堆栈大小通常比上限小,则使用双向链表,如下所述。同样,所有六个操作都是O(1)。如果堆栈的运行接近最小大小,则每个元素的存储空间是最佳的 - 您将不会有大量闲置的阵列空间。请注意,以下显示为“新”和“空闲”的内存分配可以由malloc()和free()调用组成,也可以是通过使用可用节点池限制开销的一些常用方法。
让H指向列表头,T指向尾部,M指向中间。 (M可以在每次更改时保持O(1),如下所示。)初始化列表大小s = 0和中间计数m = 0。
为您的操作1-6:
无效推送(E E):
结交新节点X与E值; ++ S;如果(s == 1)设置H = T = M = X并设置链接,否则{附加X在H;设H = X; (s/2 + 1),则{++ m和设定M = M.next}}。
void pop(E e):if s < 1 return null or error;如果(s == 0)H = T = M = null,否则如果m>(s/2),则返回H,H = H.next,取消链接并释放H.prev, +1),然后{--m并设置M = M.prev}}。
E peekMidElement(); [大小()/ 2)+1]:如果M,还给我否则返回null
ËpeekHighestElement():如果H,返回他(或Te)否则返回null
ËpeekLowestElement()?如果T,返回特否则返回null
INT尺寸()(或他):返回小号
我不知道该堆栈的到底是 “高”;你看到它正在成长,还是在成长?无论如何,只要你喜欢修复操作,并更改为像peekHeadElement或peekFirstElement等名称
所有方法都要经常调用。而且它的时间效率也很重要。 –
只有时间效率?以数组的形式实现它。 – Malvolio