栈:FILO 其实就是一端增加和一端删除的链表 一般我们对头进行增加和删除
几个必要函数:1.Init 2.Push 3.Pop 4.Clear 5.Destroy 6.GetTop 7.GetCount 8.IsEmpty
怎样销毁栈? 销毁后不能进行Push 和Pop
1.设置标志,执行销毁函数后,将标志置为false,Push 和Pop则不能执行
2.将Node结构体放入另一个结构体栈中,这样销毁了栈的地址
栈的代码:
#include "stdio.h" #include "stdlib.h" typedef struct node1 { int val; struct node1* next; }Node; typedef struct node2 { Node* pHead; int len; }Stack; Stack* s_Init() { Stack *pTop = (Stack*)malloc(sizeof(Stack)); pTop->pHead = NULL; pTop->len = 0; return pTop; } void s_Push(Stack* mystack,int data) { if(mystack == NULL) { printf("Stack not exit\n"); return ; } Node* tmp = (Node*)malloc(sizeof(Node)); tmp->val = data; tmp->next = mystack->pHead; mystack->pHead = tmp; mystack->len++; } int s_Pop(Stack* mystack) { if(mystack == NULL) { printf("Stack not exit\n"); return -1; } if(mystack->len == 0) { printf("Stack is NULL\n"); return -1; } Node * del = mystack->pHead; mystack->pHead = mystack->pHead->next; int data = del->val; free(del); del = NULL; mystack->len--; return data; } void s_Clear(Stack* mystack) { if(mystack == NULL) { printf("Stack not exit\n"); return; } while(mystack->len != 0) s_Pop(mystack); } int s_IsEmpty(Stack * mystack) { if(mystack == NULL) { printf("Stack not exit\n"); return -1; } return mystack->len == 0 ? 1 : 0; } void s_Destroy(Stack** mystack) { s_Clear(*mystack); free(*mystack); *mystack = 0; } int s_GetTop(Stack* mystack) { if(mystack == NULL) { printf("Stack not exit\n"); return -1; } return mystack->pHead->val; } int s_GetCount(Stack * mystack) { if(mystack == NULL) { printf("Stack not exit\n"); return -1; } return mystack->len; }
栈的应用:
1.斐波那契数列 黄金分割序列 最美序列
两种方法:一种:递归,一种用三个数
int Func(int n) { if(n == 1|| n == 2) return 1; return Func(n-1)+Func(n-2); } int Fbnci(int n) { int f1 = 1; int f2 = 1; int f3 = 2; int num = 3; while(num < n) { f1 = f2; f2 = f3; f3 = f1+f2; num++; } return f3; }
2.四则运算
中缀表达式
后缀表达式(逆波兰表示法)
2个数的加法运算计算机实现:先^再&(得到进位的值)将值左移一位再与^所得值相加(重复操作直到&所得值为0)
中缀->后缀:借助辅助栈,遇到数字或字符直接打印,遇到符号与栈顶元素优先级比较,符号优先级高,则直接入栈。若当前符号优先级低,则依次出栈,直到栈顶元素比当前元素优先级低为止。
遇到“( ”无条件入栈,遇到“ )”将栈内元素依次出栈,知道出到左括号为止。
中缀->后缀:所有中缀表达式括起来,将符号拿到所在符号后面
后缀->前缀:遇到数字或字符直接入栈,遇到符号将栈顶元素后一个与栈顶构成表达式。
队列:FIFO 尾添加,头删除
循环队列:数组
#include <stdio.h> #include <stdlib.h> typedef struct node { int val; struct node* next; }Node; typedef struct que { Node* pHead; Node* pEnd; int len; }Queue; Queue* Init() { Queue* myqueue =(Queue*) malloc(sizeof(Queue)); myqueue->pHead = NULL; myqueue->pEnd = NULL; myqueue->len = 0; return myqueue; } void Push(Queue* myqueue,int data) { Node* ptmp = (Node*)malloc(sizeof(Node)); ptmp->val = data; ptmp->next = NULL; if(myqueue->pEnd == NULL) { myqueue->pEnd = ptmp; myqueue->pHead = ptmp; } else { myqueue->pEnd->next = ptmp; myqueue->pEnd = ptmp; } myqueue->len++; } int Pop(Queue* myqueue) { Node* del = myqueue->pHead; myqueue->pHead = myqueue->pHead->next; int data = del->val; free(del); del = NULL; myqueue->len--; if(myqueue->len == 0) myqueue->pEnd = NULL; return data; } int IsEmpty(Queue* myqueue) { if(myqueue == NULL) return -1; return myqueue->len== 0 ? 1:0; }
两个栈模拟队列:向栈1压入元素,要弹出时将栈1元素全部弹出到栈2,从栈2取得元素,之后只要栈2不为空则从栈2取元素,为空时,再将栈1元素全部弹到栈2
#include "stdio.h" #include "stdlib.h" typedef struct node1 { int val; struct node1* next; }Node; typedef struct node2 { Node* pHead; int len; }Stack; typedef struct node3 { Stack* s1; Stack* s2; int nCount; }Queue; Stack* s_Init() { Stack *pTop = (Stack*)malloc(sizeof(Stack)); pTop->pHead = NULL; pTop->len = 0; return pTop; } void s_Push(Stack* mystack,int data) { if(mystack == NULL) { printf("Stack not exit\n"); return ; } Node* tmp = (Node*)malloc(sizeof(Node)); tmp->val = data; tmp->next = mystack->pHead; mystack->pHead = tmp; mystack->len++; } int s_Pop(Stack* mystack) { if(mystack == NULL) { printf("Stack not exit\n"); return -1; } if(mystack->len == 0) { printf("Stack is NULL\n"); return -1; } Node * del = mystack->pHead; mystack->pHead = mystack->pHead->next; int data = del->val; free(del); del = NULL; mystack->len--; return data; } Queue* q_Init() { Queue* myqueue = (Queue*)malloc(sizeof(Queue)); myqueue->s1 = s_Init(); myqueue->s2 = s_Init(); myqueue->nCount = 0; return myqueue; } void q_Push(Queue* myqueue,int data) { if(myqueue == NULL) printf("Queue not exit\n"); s_Push(myqueue->s1,data); myqueue->nCount++; } int q_Pop(Queue* myqueue) { if(myqueue == NULL) { printf("Queue not exit\n"); return -1; } if(myqueue->s2->len == 0) { while(myqueue->s1->len != 0) s_Push(myqueue->s2,s_Pop(myqueue->s1)); } return s_Pop(myqueue->s2); }
两个队列模拟栈:向队列中压入元素,当要弹出的时候,只留下最后一个,其余全部转到另一个队列中,再想非空队列中压入元素,弹出时转到另一个队列
#include <stdio.h> #include <stdlib.h> typedef struct node { int val; struct node* next; }Node; typedef struct que { Node* pHead; Node* pEnd; int len; }Queue; typedef struct sta { Queue* q1; Queue* q2; int nCount; }Stack; Queue* Init() { Queue* myqueue =(Queue*) malloc(sizeof(Queue)); myqueue->pHead = NULL; myqueue->pEnd = NULL; myqueue->len = 0; return myqueue; } void Push(Queue* myqueue,int data) { Node* ptmp = (Node*)malloc(sizeof(Node)); ptmp->val = data; ptmp->next = NULL; if(myqueue->pEnd == NULL) { myqueue->pEnd = ptmp; myqueue->pHead = ptmp; } else { myqueue->pEnd->next = ptmp; myqueue->pEnd = ptmp; } myqueue->len++; } int Pop(Queue* myqueue) { Node* del = myqueue->pHead; myqueue->pHead = myqueue->pHead->next; int data = del->val; free(del); del = NULL; myqueue->len--; if(myqueue->len == 0) myqueue->pEnd = NULL; return data; } Stack* s_Init() { Stack* mystack = (Stack*)malloc(sizeof(Stack)); mystack->q1 = Init(); mystack->q2 = Init(); mystack->nCount = 0; return mystack; } void s_Push(Stack* mystack,int data) { if(mystack->q1->len != 0) Push(mystack->q1,data); else Push(mystack->q2,data); mystack->nCount++; } int s_Pop(Stack* mystack) { if(mystack->q1->len != 0) { while(mystack->q1->len != 1) Push(mystack->q2,Pop(mystack->q1)); return Pop(mystack->q1); } else { while(mystack->q2->len != 1) Push(mystack->q1,Pop(mystack->q2)); return Pop(mystack->q2); } }