线性表的特例
栈(stack)是限定仅在表尾进行插入和删除操作的线性表
Last in First Out
ADTADT 栈(stack) Data 同线性表。元素具有相同的类型,相邻元素具有前驱和后继关系 Operation InitStack(*S): 初始化操作,建立一个空栈S。 Destroystack(*s): 若栈存在,则销毁它。 Clearstack(*s): 将栈清空。 StackEmpty(s): 若为空,返回true,否则返回false。 GetTop(s,*e): 若楼存在且非空,用e返回s的栈顶元素。 Push(*s,e): 若栈S存在,插入新元素e到横S中并成为栈顶元素。 Pop(*S,*e): 删除栈S中栈顶元素,并用e返回其值。 StackLength(s): 返回栈S的元素个数。 endADT
#### 1.3.1 栈的顺序存储结构
栈的顺序存储结构是线性表顺序存储的简单结构:顺序栈
使用数组来表达时,栈底在下标为0的位置;
c/* 插入元素 e 为新的栈顶元素 */
Status Push(SqStack *S, SElemType e)
{
if(s -> top == MAXSIZE - 1) /* 栈满 */
{
return ERROR;
}
S -> top++; /* 栈顶指针增加一 */
S -> data[S -> top] = e; /* 将新插入元素赋值给栈顶空间 */
return OK;
}
c/* 若栈不空,则删除 S 的栈顶元素,用 e 返回其值 */
Status Pop(SqStack *S, SElemType e)
{
if(s -> top == - 1)
{
return ERROR;
}
*e = S -> data[S -> top]; /* 将要删除的栈顶元素赋值给 e */
S -> top--; /* 栈顶指针减一 */
return OK;
}
ctypedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode, *LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;
int count;
}LinkStack;
c/* 插入新元素 e */
Status Push(LinkStack *S, SElemType e)
{
LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
s -> data = e;
s -> next = S -> top; /* 把当前栈顶元素赋值给新结点的直接后继 */
S -> top =s; /* 将新的结点 s 赋值给栈顶指针 */
S -> count++;
return OK;
}
c/* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回 ERROR */
Status Pop(LinkStack *S, SElemType e)
{
LinkStackPtr p;
if(StackEmpty(*S))
{
return ERROR;
}
*e = S -> top -> data;
p = S -> top; /* 将栈顶结点赋值给 p */
S -> top = S -> top -> next;/* 使得栈顶指针下移一位,指向后一结点*/
free(p); /* 释放结点 p */
S -> count--;
return OK;
}
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。公式如下:
我们把一个直接调用自己或通过一系列的调用语句间接地调用自己的函数,称做递归函数。
我们常见的标准四则运算表达式,就是中缀表达式;如: 9+(3-1)*3+10/2;
后缀表达式是后缀计算的关键;
规则:
*举例:9+(3-1)3+10/2
-> 输出:9 3 1 - 3 * + 10 2 / +
使用后缀表达式计算公式结果
举例:9 3 1 - 3 * + 10 2 / +
队列是只准许在一端进行插入操作,而在另一端进行删除操作的线性表
First In First Out
textADT 队列(Queue) Data 同线性表。元素具有相同的类型,相邻元素具有前驱和后继关系。 Operation InitQueue(*Q):初始化操作,建立一个空队列Q。 DestroyQueue(*Q):若队列Q存在,则销毁它。 ClearQueue(*Q):将队列Q清空。 QueueEmpty(Q):若队列Q为空,返回true,否则返回false。 GetHead(Q,*e):若队列Q存在且非空,用e返回队列Q的队头元素。 EnQueue(*Q,e):若队列Q存在,插入新元素e到队列Q中并成为队尾元素。 DeQueue(*Q,*e):删除队列Q中队头元素,并用e返回其值。 QueueLength(Q):返回队列Q的元素个数 endADT
使用数组来做队列存储,用下标 0 一端做队头,查入数据是直接往数组添加数据,所以时间复杂度是 O(1),队头删除数据时,所有数据往前移动,时间复杂度为O(n);
使用数组来做队列存储,front 指针指向队头下标, rear 指针指向队尾的下一个下标,当 front == rear 时为空队列,添加一个元素,rear 加 1,删除一个元素 front 加 1。这样删除和插入时间复杂度都为O(n)。
这种实现存在一个假溢出问题,当数组数据不满,但是队列不停插入和删除,导致 rear 超过了数组的 size ( front != 0)。
解决假溢出的问题就是,当后面满了重头开始,我们把队列的这种头尾相接的顺序存储结构称为循环队列。
其实就是线性表的单链表,只不过只准许尾进头出。
本文作者:Yui_HTT
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!