栈和队列的基本操作

待我称王封你为后i 2023-10-17 16:26 168阅读 0赞
  1. /*
  2. 对栈实现初始化,插入栈顶元素,删除栈顶元素,遍历栈,清空栈等基本操作
  3. */
  4. 1 #include <stdio.h>
  5. 2 #include <malloc.h>
  6. 3 #include <stdlib.h>
  7. 4
  8. 5 #define true 1
  9. 6 #define false 0
  10. 7
  11. 8
  12. 9 typedef struct Node
  13. 10 {
  14. 11 int data;
  15. 12 struct Node *pNext;
  16. 13 }NODE, *PNODE;
  17. 14
  18. 15 typedef struct Stack
  19. 16 {
  20. 17 PNODE pTop;
  21. 18 PNODE pBottom;
  22. 19 }STACK, *PSTACK;
  23. 20
  24. 21 void init(PSTACK pS);
  25. 22 void push(PSTACK pS, int val);
  26. 23 void traverse(PSTACK pS);
  27. 24 int pop(PSTACK pS , int *val);
  28. 25 void clear(PSTACK pS);
  29. 26 int empty(PSTACK pS);
  30. 27
  31. 28 int main(void)
  32. 29 {
  33. 30 STACK S ;
  34. 31 int val;
  35. 32 int i;
  36. 33
  37. 34 init(&S);
  38. 35
  39. 36 push(&S,1);
  40. 37 push(&S,2);
  41. 38 push(&S,3);
  42. 39 push(&S,4);
  43. 40 push(&S,5);
  44. 41 push(&S,6);
  45. 42
  46. 43 traverse(&S);
  47. 44
  48. 45 if(pop(&S ,&val))
  49. 46 {
  50. 47 printf("遍历成功,出栈元素为%d\n",val);
  51. 48 }
  52. 49 else
  53. 50 {
  54. 51 printf("出栈失败!\n");
  55. 52 }
  56. 53 traverse(&S);
  57. 54
  58. 55 clear(&S);
  59. 56
  60. 57 traverse(&S);
  61. 58
  62. 59 return 0 ;
  63. 60 }
  64. 61
  65. 62 //栈的初始化
  66. 63 void init(PSTACK pS)
  67. 64 {
  68. 65 pS -> pTop = (PNODE)malloc(sizeof(NODE));
  69. 66
  70. 67 if(NULL == pS -> pTop)
  71. 68 {
  72. 69 printf("动态内存分配失败!");
  73. 70 exit(-1);
  74. 71 }
  75. 72 else
  76. 73 {
  77. 74 pS -> pBottom = pS -> pTop;
  78. 75 pS -> pTop -> pNext = NULL;
  79. 76 }
  80. 77
  81. 78 return ;
  82. 79 }
  83. 80
  84. 81 //插入元素到栈顶
  85. 82 void push(PSTACK pS , int val)
  86. 83 {
  87. 84 PNODE pNew = (PNODE)malloc(sizeof(NODE));
  88. 85
  89. 86 pNew -> data = val;
  90. 87 pNew -> pNext = pS -> pTop;
  91. 88 pS -> pTop = pNew;
  92. 89
  93. 90 return ;
  94. 91 }
  95. 92
  96. 93 //遍历栈S
  97. 94 void traverse(PSTACK pS)
  98. 95 {
  99. 96 PNODE p = pS -> pTop;
  100. 97
  101. 98 printf("栈内元素为:");
  102. 99 while(p != pS -> pBottom)
  103. 100 {
  104. 101 printf("%d\t", p -> data);
  105. 102 p = p -> pNext;
  106. 103 }
  107. 104
  108. 105 printf("\n");
  109. 106 return ;
  110. 107 }
  111. 108
  112. 109 //判断栈是否为空
  113. 110 int empty(PSTACK pS)
  114. 111 {
  115. 112 if(pS -> pTop == pS -> pBottom)
  116. 113 {
  117. 114 return true;
  118. 115 }
  119. 116 else
  120. 117 return false;
  121. 118 }
  122. 119
  123. 120 //删除栈顶元素并将其值赋给*val
  124. 121 int pop(PSTACK pS , int *val)
  125. 122 {
  126. 123 if(empty(pS))
  127. 124 {
  128. 125 return false;
  129. 126 }
  130. 127 else
  131. 128 {
  132. 129 PNODE r = pS -> pTop;
  133. 130 *val = r -> data;
  134. 131 pS -> pTop = r -> pNext;
  135. 132 free(r);
  136. 133 r = NULL;
  137. 134 }
  138. 135 }
  139. 136
  140. 137 //清空栈S
  141. 138 void clear(PSTACK pS)
  142. 139 {
  143. 140 if(empty(pS))
  144. 141 {
  145. 142 return;
  146. 143 }
  147. 144 else
  148. 145 {
  149. 146 PNODE p = pS -> pTop;
  150. 147 PNODE q = NULL;
  151. 148
  152. 149 while(p != pS -> pBottom)
  153. 150 {
  154. 151 q = p -> pNext;
  155. 152 free(p);
  156. 153 p = q ;
  157. 154 }
  158. 155
  159. 156 pS -> pTop = pS -> pBottom;
  160. 157
  161. 158 return;
  162. 159 }
  163. 160 } 1.链式队列 //队列结点结构体 typedef struct QNode { QElemType data; QNode *next; }*Queueptr; ------------------------------ //指向结点的指针 struct LinkQueue { Queueptr front,rear; }
  164. <STRONG><SPAN style="COLOR: #000066; FONT-SIZE: 18px">void InitQueue(LinkQueue &Q)
  165. { // 构造一个空队列Q
  166. if(!(Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode))))
  167. exit(OVERFLOW);
  168. Q.front->next=NULL;
  169. }
  170. void DestroyQueue(LinkQueue &Q)
  171. { // 销毁队列Q(无论空否均可)
  172. while(Q.front)
  173. {
  174. Q.rear=Q.front->next;
  175. free(Q.front);
  176. Q.front=Q.rear;//释放一块内存要做两点:1.释放指向它的指针。2.将该指针指向空
  177. }
  178. }
  179. void ClearQueue(LinkQueue &Q)
  180. { // 将Q清为空队列
  181. QueuePtr p,q;
  182. Q.rear=Q.front;
  183. p=Q.front->next;
  184. Q.front->next=NULL;//只留下头结点
  185. while(p)
  186. {
  187. q=p;
  188. p=p->next;
  189. free(q);
  190. }
  191. }
  192. Status QueueEmpty(LinkQueue Q)
  193. { // 若Q为空队列,则返回TRUE,否则返回FALSE
  194. if(Q.front->next==NULL)//注意不要把链式队列的判空条件与循环队列混淆
  195. return TRUE;
  196. else
  197. return FALSE;
  198. }
  199. int QueueLength(LinkQueue Q)
  200. { // 求队列的长度
  201. int i=0;
  202. QueuePtr p;
  203. p=Q.front;
  204. while(Q.rear!=p)
  205. {
  206. i++;
  207. p=p->next;
  208. }
  209. return i;
  210. }
  211. Status GetHead(LinkQueue Q,QElemType &e)
  212. { // 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR
  213. QueuePtr p;
  214. if(Q.front==Q.rear)
  215. return ERROR;
  216. p=Q.front->next;
  217. e=p->data;
  218. return OK;
  219. }
  220. void EnQueue(LinkQueue &Q,QElemType e)
  221. { // 插入元素e为Q的新的队尾元素
  222. QueuePtr p;
  223. if(!(p=(QueuePtr)malloc(sizeof(QNode)))) // 存储分配失败
  224. exit(OVERFLOW);
  225. p->data=e;
  226. p->next=NULL;
  227. Q.rear->next=p;
  228. Q.rear=p;
  229. }
  230. Status DeQueue(LinkQueue &Q,QElemType &e)
  231. { // 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR
  232. QueuePtr p;
  233. if(Q.front==Q.rear)
  234. return ERROR;
  235. p=Q.front->next;
  236. e=p->data;
  237. Q.front->next=p->next;
  238. if(Q.rear==p)
  239. Q.rear=Q.front;//如果只有一个节点,那么删除这个节点后rear指针也就丢了,需重新赋值
  240. free(p);
  241. return OK;
  242. }
  243. void QueueTraverse(LinkQueue Q,void(*vi)(QElemType))
  244. { // 从队头到队尾依次对队列Q中每个元素调用函数vi()
  245. QueuePtr p;
  246. p=Q.front->next;
  247. while(p)
  248. {
  249. vi(p->data);
  250. p=p->next;
  251. }
  252. printf("\n");
  253. }</SPAN></STRONG>
  254. <strong><span style="font-size:18px;color:#000066;">void InitQueue(LinkQueue &Q)
  255. { // 构造一个空队列Q
  256. if(!(Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode))))
  257. exit(OVERFLOW);
  258. Q.front->next=NULL;
  259. }
  260. void DestroyQueue(LinkQueue &Q)
  261. { // 销毁队列Q(无论空否均可)
  262. while(Q.front)
  263. {
  264. Q.rear=Q.front->next;
  265. free(Q.front);
  266. Q.front=Q.rear;//释放一块内存要做两点:1.释放指向它的指针。2.将该指针指向空
  267. }
  268. }
  269. void ClearQueue(LinkQueue &Q)
  270. { // 将Q清为空队列
  271. QueuePtr p,q;
  272. Q.rear=Q.front;
  273. p=Q.front->next;
  274. Q.front->next=NULL;//只留下头结点
  275. while(p)
  276. {
  277. q=p;
  278. p=p->next;
  279. free(q);
  280. }
  281. }
  282. Status QueueEmpty(LinkQueue Q)
  283. { // 若Q为空队列,则返回TRUE,否则返回FALSE
  284. if(Q.front->next==NULL)//注意不要把链式队列的判空条件与循环队列混淆
  285. return TRUE;
  286. else
  287. return FALSE;
  288. }
  289. int QueueLength(LinkQueue Q)
  290. { // 求队列的长度
  291. int i=0;
  292. QueuePtr p;
  293. p=Q.front;
  294. while(Q.rear!=p)
  295. {
  296. i++;
  297. p=p->next;
  298. }
  299. return i;
  300. }
  301. Status GetHead(LinkQueue Q,QElemType &e)
  302. { // 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR
  303. QueuePtr p;
  304. if(Q.front==Q.rear)
  305. return ERROR;
  306. p=Q.front->next;
  307. e=p->data;
  308. return OK;
  309. }
  310. void EnQueue(LinkQueue &Q,QElemType e)
  311. { // 插入元素e为Q的新的队尾元素
  312. QueuePtr p;
  313. if(!(p=(QueuePtr)malloc(sizeof(QNode)))) // 存储分配失败
  314. exit(OVERFLOW);
  315. p->data=e;
  316. p->next=NULL;
  317. Q.rear->next=p;
  318. Q.rear=p;
  319. }
  320. Status DeQueue(LinkQueue &Q,QElemType &e)
  321. { // 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR
  322. QueuePtr p;
  323. if(Q.front==Q.rear)
  324. return ERROR;
  325. p=Q.front->next;
  326. e=p->data;
  327. Q.front->next=p->next;
  328. if(Q.rear==p)
  329. Q.rear=Q.front;//如果只有一个节点,那么删除这个节点后rear指针也就丢了,需重新赋值
  330. free(p);
  331. return OK;
  332. }
  333. void QueueTraverse(LinkQueue Q,void(*vi)(QElemType))
  334. { // 从队头到队尾依次对队列Q中每个元素调用函数vi()
  335. QueuePtr p;
  336. p=Q.front->next;
  337. while(p)
  338. {
  339. vi(p->data);
  340. p=p->next;
  341. }
  342. printf("\n");
  343. }</span></strong>
  344. 2.顺序队列---循环队列 结构体定义如下: struct SqQueue {QElemType *base;//指向开辟的空间的首地址 int front; int rear; }
  345. [cpp]
  346. view plain
  347. copy
  348. print
  349. ?
  350. void InitQueue(SqQueue &Q)
  351. { // 构造一个空队列Q
  352. Q.base=(QElemType *)malloc(MAX_QSIZE*sizeof(QElemType));
  353. if(!Q.base) // 存储分配失败
  354. exit(OVERFLOW);
  355. Q.front=Q.rear=0;
  356. }
  357. void DestroyQueue(SqQueue &Q)
  358. { // 销毁队列Q,Q不再存在
  359. if(Q.base)
  360. free(Q.base);
  361. Q.base=NULL;
  362. Q.front=Q.rear=0;
  363. }
  364. void ClearQueue(SqQueue &Q)
  365. { // 将Q清为空队列
  366. Q.front=Q.rear=0;
  367. }
  368. Status QueueEmpty(SqQueue Q)
  369. { // 若队列Q为空队列,则返回TRUE;否则返回FALSE
  370. if(Q.front==Q.rear) // 队列空的标志
  371. return TRUE;
  372. else
  373. return FALSE;
  374. }
  375. int QueueLength(SqQueue Q)
  376. { // 返回Q的元素个数,即队列的长度
  377. return(Q.rear-Q.front+MAX_QSIZE)%MAX_QSIZE;
  378. }
  379. Status GetHead(SqQueue Q,QElemType &e)
  380. { // 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR
  381. if(Q.front==Q.rear) // 队列空
  382. return ERROR;
  383. e=Q.base[Q.front];//等价于e=*(Q.base+Q.front)
  384. return OK;
  385. }
  386. Status EnQueue(SqQueue &Q,QElemType e)
  387. { // 插入元素e为Q的新的队尾元素
  388. if((Q.rear+1)%MAX_QSIZE==Q.front) // 队列满
  389. return ERROR;
  390. Q.base[Q.rear]=e;//等价于*(Q.base+Q.rear)=e
  391. Q.rear=(Q.rear+1)%MAX_QSIZE;
  392. return OK;
  393. }
  394. Status DeQueue(SqQueue &Q,QElemType &e)
  395. { // 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR
  396. if(Q.front==Q.rear) // 队列空
  397. return ERROR;
  398. e=Q.base[Q.front];
  399. Q.front=(Q.front+1)%MAX_QSIZE;
  400. return OK;
  401. }
  402. void QueueTraverse(SqQueue Q,void(*vi)(QElemType))
  403. { // 从队头到队尾依次对队列Q中每个元素调用函数vi()
  404. int i;
  405. i=Q.front;
  406. while(i!=Q.rear)
  407. {
  408. vi(Q.base[i]);
  409. i=(i+1)%MAX_QSIZE;
  410. }
  411. printf("\n");
  412. }

发表评论

表情:
评论列表 (有 0 条评论,168人围观)

还没有评论,来说两句吧...

相关阅读

    相关 基本操作

    目录 一、什么是队列? 二、用数组实现队列 代码实现: 数组实现的缺点: 三、用链表实现队列 代码实现: -------------------- 一、什么

    相关 循环基本操作

    循环队列设置不同队空与队满条件的解决方案 为了解决顺序队列假溢出的问题,我们采用的方案是少用一个元素空间,此时的指针状态是队尾指针加1才与队头指针重合,于是此时队满的判定