• 数据结构与算法3---栈与队


    一、栈

    1、顺序栈

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. #include //开辟空间
    4. #define MAXSIZE 50
    5. //顺序栈的基本算法
    6. typedef struct {
    7. int stack[MAXSIZE];
    8. int top;
    9. }SqStack;
    10. //初始化
    11. void InitStack(SqStack* S) {
    12. S->top = -1;
    13. }
    14. //判断栈是否为空
    15. int StackEmpty(SqStack S) {
    16. if (S.top == -1) {
    17. return 1;
    18. }
    19. return 0;
    20. }
    21. //进栈
    22. void StackPush(SqStack* S,int x) {
    23. if (S->top == MAXSIZE - 1) {
    24. printf("此时栈满");
    25. }
    26. else {
    27. if (S->top == -1) {
    28. S->top += 1;
    29. S->stack[S->top] = x;
    30. }
    31. else {
    32. S->stack[++S->top] = x;
    33. }
    34. //printf("入栈成功");
    35. }
    36. }
    37. //出栈
    38. int StackPop(SqStack* S) {
    39. if (S->top == -1) {
    40. printf("此时为空栈,无法继续出栈");
    41. return - 1;
    42. }
    43. else {
    44. int x = S->stack[S->top];
    45. S->top--;
    46. return x;
    47. }
    48. }
    49. //取栈顶元素
    50. int GetStackTop(SqStack* S) {
    51. if (S->top == -1) {
    52. return -1;
    53. }
    54. int x = S->stack[S->top];
    55. return x;
    56. }
    57. void StackPrint(SqStack* S) {
    58. int num = S->top;
    59. while (num != -1) {
    60. printf("%d ", S->stack[num]);
    61. num--;
    62. }
    63. }
    64. int main() {
    65. SqStack* S = (SqStack*)malloc(sizeof(SqStack));
    66. InitStack(S);
    67. int a;
    68. scanf("%d", &a);
    69. while (a != 0) {
    70. StackPush(S, a);
    71. scanf("%d", &a);
    72. }
    73. StackPrint(S);
    74. a = StackPop(S);
    75. printf("%d",a);
    76. StackPrint(S);
    77. return 0;
    78. }

    2、链栈

            通过单链表实现

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. #include //开辟空间
    4. #define MAXSIZE 50
    5. //链栈
    6. typedef struct StackNode {
    7. int data;
    8. struct StackNode* next;
    9. }StackNode,*LinkStack;
    10. //初始化
    11. void InitStack(LinkStack S) {
    12. S->next = NULL;
    13. S->data = 0;
    14. }
    15. //判断链栈是否为空
    16. int EmptyStack(LinkStack S) {
    17. if (S->data == 0)
    18. return 1;
    19. return 0;
    20. }
    21. //进栈
    22. void StackPush(LinkStack S, int x) {
    23. LinkStack p = (LinkStack)malloc(sizeof(StackNode));
    24. p->data = x;
    25. p->next = S->next;
    26. S->next = p;
    27. S->data++;
    28. }
    29. //出栈
    30. int StackPop(LinkStack S) {
    31. LinkStack p = S->next;
    32. if (p == NULL)
    33. return -1;
    34. S->next = p->next;
    35. int a = p->data;
    36. free(p);
    37. S->data--;
    38. return a;
    39. }
    40. //打印
    41. void StackPrint(LinkStack S) {
    42. LinkStack p = S->next;
    43. while (p) {
    44. printf("%d ", p->data);
    45. p = p->next;
    46. }
    47. }
    48. int main() {
    49. LinkStack S = (LinkStack)malloc(sizeof(StackNode));
    50. InitStack(S);
    51. StackPush(S, 1);
    52. StackPush(S, 2);
    53. StackPush(S, 3);
    54. StackPrint(S);
    55. int x = StackPop(S);
    56. printf("%d", x);
    57. StackPrint(S);
    58. return 0;
    59. }

    3.卡特兰数

    C_{_{n}} = C_{2n}^{n} - C_{2n}^{n-1}

    1. 出栈次序

    一个栈(无穷大)的进栈序列为1,2,3,…,n,有多少个不同的出栈序列?


     C_{2n}^{n}下面这个2n是什么意思?

    假如有4个数。那每个数有两个情况一个进栈和出栈两种状态。那就一共有8种状态

    如果有n个数就有2n种状态。


    C_{2n}^{n}上面那个n是什么意思?

    栈进栈再出栈。假如将进栈标记为1。将出栈标记为-1。出栈和进栈是要平衡的和要为0所以代表n个数里面有几种进栈的状态4个数的话就会有4种进栈的状态。

    这里我们记:进栈--- +1        出栈--- -1

    有以下结论:

    1. 合法序列必定总和为0,即num(-1)=num(+1)
    2. 总和为0的序列不一定合法

    有 合法 = C_{2n}^{n} - 非法

            3.“前缀”:包含首个元素往后数

            4.合法序列的特点:对于所有前缀,每一个前缀的和都>=0,且num(-1)=num(+1)

    比如: n=3

    不合法的:+1,-1,-1,+1,-1,+1

    合法的: +1,-1,+1,+1,+1,-1,-1

    对于第一个:将第一个“和小于0”的前缀取反,得到一个新序列

    -1,+1,+1,+1,-1,+1此时就有4个+1,2个-1

    对应n个的话就是将第一个“和小于零”的前缀取反,就得到新序列,且有n+1个+1,n-1个-1

    所以A和B是一一对应的

    4、表达式求值

    【问题描述】栈的应用,给定一个以“#”作为结束符的算式,求出算式的结果

    【输入形式】以“#”结尾的表达式,运算数为正整数。每个表达式占一行。

    【输出形式】输出表达式运算的结果。

    【样例输入1】4+2.53*3-10/5#

    【样例输出1】9.59

    【样例输入2】3*(7.91-2)#

    【样例输出2】17.73

    【样例输入3】2.4*3.6/2#

    【样例输出3】4.32

    【注意】要处理表达式中带小数的数据,不能仅采用getchar去接收数据,请注意查阅资料,看看如何处理。

    另外,输出数据请保留2位小数。

    1. #include
    2. #define TRUE 1
    3. #define FALSE 0
    4. #define Size 50
    5. typedef struct {
    6. float elem[Size];
    7. int top;
    8. }SeqStack;
    9. void Init(SeqStack* S) {
    10. S->top = -1;
    11. }
    12. int Empty(SeqStack* S) {
    13. return(S->top == -1 ? TRUE : FALSE);
    14. }
    15. int Full(SeqStack* S) {
    16. return(S->top == Size - 1 ? TRUE : FALSE);
    17. }
    18. int Push(SeqStack* S, float x) {
    19. if (S->top == Size - 1) {
    20. return FALSE;
    21. }
    22. S->top++;
    23. S->elem[S->top] = x;
    24. return TRUE;
    25. }
    26. int Pop(SeqStack* S, float* x) {
    27. if (S->top == -1) {
    28. return FALSE;
    29. }
    30. else {
    31. *x = S->elem[S->top];
    32. S->top--;
    33. return TRUE;
    34. }
    35. }
    36. int Get(SeqStack* S, float* x) {
    37. if (S->top == -1) {
    38. return FALSE;
    39. }
    40. else {
    41. *x = S->elem[S->top];
    42. return TRUE;
    43. }
    44. }
    45. typedef struct {
    46. char elem[Size];
    47. int top;
    48. }StrStack;
    49. void StrInit(StrStack* s) {
    50. s->top = -1;
    51. }
    52. int StrEmpty(StrStack* s) {
    53. return(s->top == -1 ? TRUE : FALSE);
    54. }
    55. int StrFull(SeqStack* s) {
    56. return(s->top == Size - 1 ? TRUE : FALSE);
    57. }
    58. int StrPush(StrStack* s, char x) {
    59. if (s->top == Size - 1) {
    60. return FALSE;
    61. }
    62. s->top++;
    63. s->elem[s->top] = x;
    64. return TRUE;
    65. }
    66. int StrPop(StrStack* s, char* x) {
    67. if (s->top == -1) {
    68. return FALSE;
    69. }
    70. else {
    71. *x = s->elem[s->top];
    72. s->top--;
    73. return TRUE;
    74. }
    75. }
    76. int StrGet(StrStack* s, char* x) {
    77. if (s->top == -1) {
    78. return FALSE;
    79. }
    80. else {
    81. *x = s->elem[s->top];
    82. return TRUE;
    83. }
    84. }
    85. int match(char ch, char str) {
    86. if (ch == '(' && str == ')') {
    87. return TRUE;
    88. }
    89. else if (ch == '[' && str == ']') {
    90. return TRUE;
    91. }
    92. else if (ch == '{' && str == '}') {
    93. return TRUE;
    94. }
    95. else return FALSE;
    96. }
    97. int In(char ch) {
    98. if (ch == '+') {
    99. return TRUE;
    100. }
    101. else if (ch == '-') {
    102. return TRUE;
    103. }
    104. else if (ch == '*') {
    105. return TRUE;
    106. }
    107. else if (ch == '/') {
    108. return TRUE;
    109. }
    110. else if (ch == '(') {
    111. return TRUE;
    112. }
    113. else if (ch == ')') {
    114. return TRUE;
    115. }
    116. else if (ch == '#') {
    117. return TRUE;
    118. }
    119. else return FALSE;
    120. }
    121. char Comper(char x, char ch) {
    122. switch (x)
    123. {
    124. case'+':
    125. if (ch == '+' || ch == '-' || ch == ')' || ch == '#')
    126. return '>';
    127. else if (ch == '*' || ch == '/' || ch == '(')
    128. return '<';
    129. break;
    130. case'-':
    131. if (ch == '+' || ch == '-' || ch == ')' || ch == '#')
    132. return '>';
    133. else if (ch == '*' || ch == '/' || ch == '(')
    134. return '<';
    135. break;
    136. case'*':
    137. if (ch == '(') {
    138. return '<';
    139. }
    140. else {
    141. return '>';
    142. }
    143. break;
    144. case'/':
    145. if (ch == '(') {
    146. return '<';
    147. }
    148. else {
    149. return '>';
    150. }
    151. break;
    152. case'(':
    153. if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(')
    154. return '<';
    155. else if (ch == ')')
    156. return '=';
    157. else if (ch == '#')
    158. return '0';
    159. break;
    160. case')':
    161. if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == ')' || ch == '#')
    162. return '>';
    163. else if (ch == '(')
    164. return '0';
    165. break;
    166. case'#':
    167. if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(')
    168. return '<';
    169. else if (ch == '#')
    170. return '=';
    171. else if (ch == ')')
    172. return '0';
    173. break;
    174. default:
    175. return '0';
    176. break;
    177. }
    178. }
    179. /*
    180. char Operator(char a, char b) {
    181. int i = 0, j = 0;
    182. char pre[7][7] = {
    183. {'>','>','<','<','<','>','>'},
    184. {'>','>','<','<','<','>','>'},
    185. {'>','>','>','>','<','>','>'},
    186. {'>','>','>','>','<','>','>'},
    187. {'<','<','<','<','<','=','0'},
    188. {'>','>','>','>','0','>','>'},
    189. {'<','<','<','<','<','0','='},
    190. };
    191. switch (a) {
    192. case'+':i = 0; break;
    193. case'-':i = 1; break;
    194. case'*':i = 2; break;
    195. case'/':i = 3; break;
    196. case'(':i = 4; break;
    197. case')':i = 5; break;
    198. case'#':i = 6; break;
    199. }
    200. switch (b) {
    201. case'+':j = 0; break;
    202. case'-':j = 1; break;
    203. case'*':j = 2; break;
    204. case'/':j = 3; break;
    205. case'(':j = 4; break;
    206. case')':j = 5; break;
    207. case'#':j = 6; break;
    208. }
    209. return pre[i][j];
    210. }
    211. */
    212. float Execute(float a, char op, float b) {
    213. switch (op) {
    214. case'+':
    215. return (a + b);
    216. break;
    217. case'-':
    218. return (a - b);
    219. break;
    220. case'*':
    221. return (a * b);
    222. break;
    223. case'/':
    224. if (b != 0)
    225. return (a / b);
    226. else
    227. return 0;
    228. break;
    229. }
    230. }
    231. char ch;
    232. float Evaluation() {
    233. char x, y;
    234. char op;
    235. float a, b, v;
    236. SeqStack data;
    237. StrStack sign;
    238. Init(&data);
    239. StrInit(&sign);
    240. StrPush(&sign, '#'); //提前压一个符号进栈
    241. //printf("biaodashi:\n");
    242. ch = getchar();
    243. StrGet(&sign, &y);
    244. while (ch != '#' || y != '#') {
    245. if (!In(ch)) {
    246. int temp;
    247. int i = 1;
    248. float temp2, a[10] = { 0,0.1,0.01,0.001,0.0001,0.00001 };
    249. temp = ch - '0'; //转换为数字
    250. ch = getchar();
    251. while (!In(ch) && ch != '.') {
    252. temp = temp * 10 + ch - '0';
    253. ch = getchar();
    254. }
    255. temp2 = temp;
    256. if (ch == '.') {
    257. ch = getchar();
    258. for (i = 1; !In(ch); i++) {
    259. temp2 += (ch - '0') * a[i];
    260. ch = getchar();
    261. }
    262. }
    263. Push(&data, temp2);
    264. }
    265. else {
    266. switch (Comper(y, ch)) {
    267. case'<':
    268. StrPush(&sign, ch);
    269. ch = getchar();
    270. break;
    271. case'=':
    272. StrPop(&sign, &x);
    273. ch = getchar();
    274. break;
    275. case'>':
    276. StrPop(&sign, &op);
    277. Pop(&data, &b);
    278. Pop(&data, &a);
    279. v = Execute(a, op, b);
    280. Push(&data, v);
    281. break;
    282. }
    283. }
    284. StrGet(&sign, &y);
    285. }
    286. Get(&data, &v);
    287. return(v);
    288. }
    289. int main() {
    290. float result;
    291. result = Evaluation();
    292. printf("\n%.2f", result);
    293. return 0;
    294. }

    二、队列

    1、链队列

    先进先出

    1. #include
    2. #include
    3. typedef struct Node {
    4. int data;
    5. struct Node* next;
    6. }Node;
    7. Node* initQueue() {
    8. Node* Q = (Node*)malloc(sizeof(Node));
    9. Q->data = 0;
    10. Q->next = NULL;
    11. return Q;
    12. }
    13. void inQueue(Node* Q, int data) {
    14. Node* node = (Node*)malloc(sizeof(Node));
    15. Node* q = Q;
    16. node->data = data;
    17. for (int i = 0; i < Q->data; i++) {
    18. q = q->next;
    19. }
    20. node->next = q->next;
    21. q->next = node;
    22. Q->data++;
    23. }
    24. int isEmpty(Node* Q) {
    25. if (Q->data == 0 || Q->next == NULL)
    26. return 1;
    27. return 0;
    28. }
    29. int delQueue(Node* Q) {
    30. if (isEmpty(Q))
    31. return -1;
    32. Node* node = Q->next;
    33. int data = node->data;
    34. Q->next = node->next;
    35. free(node);
    36. Q->data--;
    37. return data;
    38. }
    39. void printQueue(Node* Q) {
    40. Node* node = Q->next;
    41. while(node) {
    42. printf("%d ", node->data);
    43. node = node->next;
    44. }
    45. printf("NULL\n");
    46. }
    47. int main() {
    48. Node* Q = initQueue();
    49. inQueue(Q,1);
    50. inQueue(Q, 2);
    51. inQueue(Q, 3);
    52. inQueue(Q, 4);
    53. printQueue(Q);
    54. int x = delQueue(Q);
    55. printQueue(Q);
    56. printf("%d", x);
    57. return 0;
    58. }

    2、循环队列

    1. #include
    2. #include
    3. #define MAXSIZE 5
    4. //只能放4个数据,牺牲了一个空间去更好判断是否满队
    5. typedef struct Queue {
    6. int front;
    7. int rear;
    8. int data[MAXSIZE];
    9. }Queue;
    10. Queue* initQueue() {
    11. Queue* Q = (Queue*)malloc(sizeof(Queue));
    12. Q->front = Q->rear = 0;
    13. return Q;
    14. }
    15. int isFull(Queue* Q) {
    16. if ((Q->rear + 1) % MAXSIZE == Q->front) {
    17. return 1;
    18. }
    19. return 0;
    20. }
    21. int isEmpty(Queue* Q) {
    22. if (Q->front == Q->rear)
    23. return 1;
    24. return 0;
    25. }
    26. int inQueue(Queue* Q,int data) {
    27. if (isFull(Q)) {
    28. return 0;
    29. }
    30. else {
    31. Q->data[Q->rear] = data;
    32. Q->rear = (Q->rear + 1) % MAXSIZE;
    33. return 1;
    34. }
    35. }
    36. int delQueue(Queue* Q) {
    37. if (isEmpty(Q))
    38. return -1;
    39. int data = Q->data[Q->front];
    40. Q->front = (Q->front + 1) % MAXSIZE;
    41. return data;
    42. }
    43. void printQueue(Queue* Q) {
    44. int length = (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
    45. int index = Q->front;
    46. for (int i = 0; i < length; i++) {
    47. printf("%d->", Q->data[index]);
    48. index = (index + 1) % MAXSIZE;
    49. }
    50. printf("NULL\n");
    51. }
    52. void main() {
    53. Queue* Q = initQueue();
    54. inQueue(Q, 1);
    55. inQueue(Q, 2);
    56. inQueue(Q, 3);
    57. inQueue(Q, 4);
    58. printQueue(Q);
    59. delQueue(Q);
    60. printQueue(Q);
    61. return 0;
    62. }

    3、杨辉三角

    1. #include
    2. #define MAX 100
    3. #define FALSE 0
    4. #define TRUE 1
    5. //循环队列
    6. typedef struct {
    7. int element[MAX];
    8. int front; //头指针
    9. int rear; //尾指针
    10. } SeqQueue;
    11. //初始化循环队列
    12. void InitQueue(SeqQueue* q) { q->front = q->rear = 0; }
    13. //入队
    14. int EnterQueue(SeqQueue* q, int x) {
    15. if ((q->rear + 1) % MAX == q->front) {
    16. printf("---队列已满---");
    17. return FALSE;
    18. }
    19. q->element[q->rear] = x;
    20. q->rear = (q->rear + 1) % MAX;
    21. return TRUE;
    22. }
    23. //出队
    24. int DeleteQueue(SeqQueue* q, int* x) {
    25. if (q->front == q->rear) {
    26. printf("---队列为空---");
    27. return FALSE;
    28. }
    29. *x = q->element[q->front];
    30. q->front = (q->front + 1) % MAX;
    31. return TRUE;
    32. }
    33. //取对头元素
    34. int GetHead(SeqQueue* q, int* x) {
    35. if (q->front == q->rear)
    36. return FALSE;
    37. *x = q->element[q->front];
    38. return TRUE;
    39. }
    40. //判断队列是否为空
    41. int IsEmpty(SeqQueue* q) {
    42. if (q->front == q->rear)
    43. return TRUE;
    44. else
    45. return FALSE;
    46. }
    47. //打印杨辉三角
    48. void YangHuiTriangle(int N) {
    49. SeqQueue q;
    50. InitQueue(&q);
    51. int n, i, x, temp;
    52. EnterQueue(&q, 1); //第一行元素入队
    53. for (n = 2; n <= N; n++) {
    54. EnterQueue(&q, 1); //第n行第一个元素入队
    55. // N为打印的行数,n为每行的元素个数
    56. for (i = 1; i <= n - 2; i++) { //利用队中第n-1行元素产生第n行的中间n-2个元素并入队
    57. DeleteQueue(&q, &temp); //出队元素赋给temp
    58. printf("%d ", temp); //打印第n-1行的元素
    59. GetHead(&q, &x);
    60. temp = temp + x; //利用第n-1行元素产生第n行元素
    61. EnterQueue(&q, temp); //可以利用画图理解
    62. }
    63. DeleteQueue(&q, &x);
    64. printf("%d ", x); //打印n-1行最后一个元素
    65. EnterQueue(&q, 1);
    66. printf("\n");
    67. }
    68. while (!IsEmpty(&q)) { //打印最后一行
    69. DeleteQueue(&q, &x);
    70. printf("%d ", x);
    71. }
    72. }
    73. //主函数:
    74. int main() {
    75. int N;
    76. scanf("%d", &N);
    77. YangHuiTriangle(N);
    78. printf("\n");
    79. return 0;
    80. }
  • 相关阅读:
    软件测试面试复习题(一)
    AnkiPDF Guru软件评测:打开全新学习方式的大门
    这一篇让你彻底搞懂 JAVA 内部类
    信号量、互斥锁、计数信号量
    Typescript 之 快速入门
    CCS3.3烧写说明
    激活函数之ReLU, GeLU, SwiGLU
    14天学习训练营导师课程-Pygame学习笔记-Part2(第九艺术的召唤)
    codeforces:dp专练【关于子数组求和 + 选or不选来dp + 二维dp】
    5.Nginx负载均衡实例
  • 原文地址:https://blog.csdn.net/2303_79741845/article/details/139834730