堆栈(stack)又称为栈或堆叠,是只允许在一端进行插入或删除操作的线性表,遵循先进后出 FILO(First In Last Out)的原则。队列(Queue)简称队,也是一种操作受限的线性表,只允许在表的一端进行插入,而在表的另一端进行删除。向队列中插入元素称为入队或进队,删除元素称为出队或离队。以下为我在学习和实战练习过程中所做的笔记,可供参考。
一、栈的基本操作 栈顶(Top)入栈、出栈:
1 2 3 4 5 6 #define MaxSize 50 typedef int ElemType;typedef struct { ElemType data[MaxSize]; int top; }SqStack;
实现栈可以用数组,也可以用链表,我们这里使用数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 int main () { SqStack S; bool flag; ElemType m; InitStack (S); flag=StackEmpty (S); if (flag) { printf ("栈是空的\n" ); } Push (S,3 ); Push (S,4 ); Push (S,5 ); flag=GetTop (S,m); if (flag) { printf ("获取栈顶元素为 %d\n" ,m); } flag=Pop (S,m); if (flag) { printf ("弹出元素为 %d\n" ,m); } system ("pause" ); }
初始化栈:
1 2 3 4 5 6 7 8 9 10 11 12 void InitStack (SqStack &S) { S.top=-1 ; } bool StackEmpty (SqStack &S) { if (S.top==-1 ) return true ; else return false ; }
入栈:
1 2 3 4 5 6 7 8 9 bool Push (SqStack &S,ElemType x) { if (S.top==MaxSize-1 ) { return false ; } S.data[++S.top]=x; return true ; }
出栈:
1 2 3 4 5 6 7 bool Pop (SqStack &S,ElemType &x) { if (-1 ==S.top) return false ; x=S.data[S.top--]; return true ; }
读取栈顶元素:
1 2 3 4 5 6 7 bool GetTop (SqStack &S,ElemType &x) { if (-1 ==S.top) return false ; x=S.data[S.top]; return true ; }
二、循环队列 队列的特性是先进先出(FIFO),队头(Front)是允许删除的一端,又称队首,队尾(Rear)是允许插入的一端。
1 2 3 4 5 6 #define MaxSize 5 typedef int ElemType;typedef struct { ElemType data[MaxSize]; int front,rear; }SqQueue;
循环队列的操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 int main () { SqQueue Q; bool ret; ElemType element; InitQueue (Q); ret=isEmpty (Q); if (ret) { printf ("队列为空\n" ); }else { printf ("队列不为空\n" ); } EnQueue (Q,3 ); EnQueue (Q,4 ); EnQueue (Q,5 ); ret=EnQueue (Q,6 ); ret=EnQueue (Q,7 ); if (ret) { printf ("入队成功\n" ); }else { printf ("入队失败\n" ); } ret=DeQueue (Q,element); if (ret) { printf ("出队成功,元素值为 %d\n" ,element); }else { printf ("出队失败\n" ); } ret=DeQueue (Q,element); if (ret) { printf ("出队成功,元素值为 %d\n" ,element); }else { printf ("出队失败\n" ); } ret=EnQueue (Q,8 ); if (ret) { printf ("入队成功\n" ); }else { printf ("入队失败\n" ); } system ("pause" ); }
初始化队列:
1 2 3 4 5 6 7 8 9 10 11 12 void InitQueue (SqQueue &Q) { Q.rear=Q.front=0 ; } bool isEmpty (SqQueue &Q) { if (Q.rear==Q.front) return true ; else return false ; }
入队:
1 2 3 4 5 6 7 8 bool EnQueue (SqQueue &Q,ElemType x) { if ((Q.rear+1 )%MaxSize==Q.front) return false ; Q.data[Q.rear]=x; Q.rear=(Q.rear+1 )%MaxSize; return true ; }
出队:
1 2 3 4 5 6 7 8 bool DeQueue (SqQueue &Q,ElemType &x) { if (Q.rear==Q.front) return false ; x=Q.data[Q.front]; Q.front=(Q.front+1 )%MaxSize; return true ; }
三、队列的链式存储 队列的链式表示称为链队列,它实际上是一个同时带有队头指针和队尾指针的单链表。头指针指向队头结点,尾指针指向队尾结点,即单链表的最后一个结点。
存储结构相对于原有编号的链表增加了尾指针:
1 2 3 4 5 6 7 8 typedef int ElemType;typedef struct LinkNode { ElemType data; struct LinkNode *next; }LinkNode; typedef struct { LinkNode *front,*rear; }LinkQueue;
头部删除法,尾部插入法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int main () { LinkQueue Q; bool ret; ElemType element; InitQueue (Q); EnQueue (Q,3 ); EnQueue (Q,4 ); EnQueue (Q,5 ); EnQueue (Q,6 ); EnQueue (Q,7 ); ret=DeQueue (Q,element); if (ret) { printf ("出队成功,元素值为 %d\n" ,element); }else { printf ("出队失败\n" ); } system ("pause" ); }
初始化队列:
1 2 3 4 5 6 7 8 9 10 11 12 void InitQueue (LinkQueue &Q) { Q.front=Q.rear=(LinkNode*)malloc (sizeof (LinkNode)); Q.front->next=NULL ; } bool IsEmpty (LinkQueue Q) { if (Q.front==Q.rear) return true ; else return false ; }
入队,尾部插入法:
1 2 3 4 5 6 7 void EnQueue (LinkQueue &Q,ElemType x) { LinkNode *s=(LinkNode *)malloc (sizeof (LinkNode)); s->data=x;s->next=NULL ; Q.rear->next=s; Q.rear=s; }
出队,头部删除法:
1 2 3 4 5 6 7 8 9 10 11 bool DeQueue (LinkQueue &Q,ElemType &x) { if (Q.front==Q.rear) return false ; LinkNode *p=Q.front->next; x=p->data; Q.front->next=p->next; if (Q.rear==p) Q.rear=Q.front; free (p); return true ; }
四、斐波那契数列 题目:n 个台阶,每次只能上 1 个台阶,或者 2 个台阶,n 个台阶,有多少种走法?
题解:Fib 是递归函数,调用自身,$f(n)=f(n-1)+f(n-2)$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int Fib (int n) { if (n==0 ) return 0 ; else if (n==1 ) return 1 ; else return Fib(n-1 )+Fib(n-2 ); } nt main () { int num; while (scanf ("%d" ,&num)!=EOF) { printf ("Fib(%d) = %d\n" ,num,Fib(num)); } system("pause" ); }