(C语言版)栈和队列(一)——实现链式栈和链式队列的基本操作以及遇到的问题
2014-02-27 16:49
751 查看
首先要感谢这位大牛的一篇博客,地址如下:http://blog.csdn.net/hguisu/article/details/7674195
当然还有网上一些其他的资料,今天自己写了一下链式栈和链式队列的程序。其中在释放内存的时候遇到了些许问题,通过调,找出了原因,在这里我与大家分享一下。
(1)链式栈的相关代码块
Stack.h 头文件——定义了节点结构和链式栈结构,以及基本操作函数的声明部分
Stack.cpp 源文件——定义链式栈的基本操作函数的定义
说明:一开始对栈初始化,但是这个栈是没有头节点的,直接定义了一个指针(top)刚开始指向NULL。
入栈的时候就是让top指针始终指向栈顶元素,入栈的节点的指针指向top指针,这样不断的进行入栈操作,节点不断增加,但是top指针一直是指针最后插入的节点。
出栈的时候就是从top指针指向的节点还是释放,然后让top指针指向被释放节点的下一个节点,这样节点不断释放,top指针不断向下移动。
所以,栈就成了一个“先进后出”的结构。
main.cpp 测试程序——通过简单的交互界面测试函数的功能
(2)链式队列的相关代码
Queue.h 头文件——定义了节点结构和队列结构,以及链式队列的基本操作函数的声明
Queue.cpp 源文件——定义了基本操作函数的定义
说明:一开始对链式队列进行初始化,这里就创建了一个节点(但是记得后面释放内存的时候这里也要释放),创建了这个节点是为了方便后面的操作,这样一开始队列的头指针和尾指针都指向了这个节点,但是此时的队列是空的,就像循环链表里头节点不参与运行是一样的道理。
入队列的时候就是进入的节点排在初始化时创建的节点后面,然后尾指针指针指着新进入的节点,但是头指针不动,节点不断进入队列,尾指针不断向后移动,保持尾指针一直指着刚进入的节点。
出队列的时候就是让头指针指向的节点的指针指向要释放节点的下一个节点,节点不断出队列,这里头指针实质上并没有移动,但是它指向的节点的指针一直在变化,一直保持者指向要释放节点的下一个节点,但是这里要注意,就是当队列中只剩下一个节点的时候(这里不包含初始化创建的那个节点),释放了这个节点以后尾指针成了野指针,那么这个时候就要让尾指针和头指针指向同一位置,那么这样判断队列是否为空的时候就是空了。
main.cpp 测试程序——简单的交互界面测试函数功能
当然还有网上一些其他的资料,今天自己写了一下链式栈和链式队列的程序。其中在释放内存的时候遇到了些许问题,通过调,找出了原因,在这里我与大家分享一下。
(1)链式栈的相关代码块
Stack.h 头文件——定义了节点结构和链式栈结构,以及基本操作函数的声明部分
#ifndef _STACK_H_H #define _STACK_H_H typedef struct Node { int data; struct Node *pNext; }NODE, *pNODE; typedef struct Stack { pNODE top; }STACK, *pSTACK; //栈初始化 void InitStack(pSTACK stack); //入栈 void PushStack(pSTACK stack, int data); //出栈 void PopStack(pSTACK stack, int *data); //判断栈是否为空 int IsEmptyStack(pSTACK stack); //获得栈顶元素 int GetTopStack(pSTACK stack); //释放内存 void FreeMemory(pSTACK stack); #endif
Stack.cpp 源文件——定义链式栈的基本操作函数的定义
说明:一开始对栈初始化,但是这个栈是没有头节点的,直接定义了一个指针(top)刚开始指向NULL。
入栈的时候就是让top指针始终指向栈顶元素,入栈的节点的指针指向top指针,这样不断的进行入栈操作,节点不断增加,但是top指针一直是指针最后插入的节点。
出栈的时候就是从top指针指向的节点还是释放,然后让top指针指向被释放节点的下一个节点,这样节点不断释放,top指针不断向下移动。
所以,栈就成了一个“先进后出”的结构。
#include "Stack.h" #include <stdlib.h> #include <stdio.h> //栈初始化 void InitStack(pSTACK stack) { stack->top = NULL; } //入栈 void PushStack(pSTACK stack, int data) { pNODE p_new = (pNODE)malloc(sizeof(NODE)); if (NULL == p_new) { printf("内存分配失败!\n"); exit(EXIT_FAILURE); } p_new->data = data; p_new->pNext = stack->top; //这里要注意 stack->top = p_new; } //出栈 void PopStack(pSTACK stack, int *data) { pNODE p_delete = stack->top; if (IsEmptyStack(stack)) exit(EXIT_FAILURE); *data = p_delete->data; stack->top = p_delete->pNext; free(p_delete); p_delete = NULL; } //判断栈是否为空 int IsEmptyStack(pSTACK stack) { if (stack->top == NULL) return 1; else return 0; } //获得栈顶元素 int GetTopStack(pSTACK stack) { int data; if (stack->top == NULL) exit(EXIT_FAILURE); data = stack->top->data; return data; } //释放内存 void FreeMemory(pSTACK stack) { pNODE p_delete = NULL; while (stack->top != NULL) { p_delete = stack->top; stack->top = p_delete->pNext; free(p_delete); p_delete = NULL; } }
main.cpp 测试程序——通过简单的交互界面测试函数的功能
#include <stdio.h> #include "Stack.h" int main(void) { int number, i, data, flag; STACK s; InitStack(&s); printf("请输入入栈个数:"); scanf("%d", &number); for (i=1; i<number+1; i++) { printf("请输入第%d个栈点元素值:", i); scanf("%d", &data); PushStack(&s, data); } PopStack(&s ,&data); printf("出栈的元素值为:%d\n", data); data = GetTopStack(&s); printf("当前栈顶元素值为:%d\n", data); FreeMemory(&s); flag = IsEmptyStack(&s); if (flag) printf("内存释放成功!\n"); else printf("内存释放失败!\n"); return 0; }
(2)链式队列的相关代码
Queue.h 头文件——定义了节点结构和队列结构,以及链式队列的基本操作函数的声明
#ifndef _QUEUE_H_H #define _QUEUE_H_H typedef struct Node { int data; struct Node *pNext; }NODE, *pNODE; typedef struct Queue { pNODE front; pNODE rear; }QUEUE, *pQUEUE; //初始化队列 void InitQueue(pQUEUE queue); //入队列 void EnQueue(pQUEUE queue, int data); //出队列 void DeQueue(pQUEUE queue, int *data); //判断队列是否为空 int IsEmptyQueue(pQUEUE queue); //获得队头元素值 int GetFrontQueue(pQUEUE queue); //释放内存 void FreeMemory(pQUEUE queue); #endif
Queue.cpp 源文件——定义了基本操作函数的定义
说明:一开始对链式队列进行初始化,这里就创建了一个节点(但是记得后面释放内存的时候这里也要释放),创建了这个节点是为了方便后面的操作,这样一开始队列的头指针和尾指针都指向了这个节点,但是此时的队列是空的,就像循环链表里头节点不参与运行是一样的道理。
入队列的时候就是进入的节点排在初始化时创建的节点后面,然后尾指针指针指着新进入的节点,但是头指针不动,节点不断进入队列,尾指针不断向后移动,保持尾指针一直指着刚进入的节点。
出队列的时候就是让头指针指向的节点的指针指向要释放节点的下一个节点,节点不断出队列,这里头指针实质上并没有移动,但是它指向的节点的指针一直在变化,一直保持者指向要释放节点的下一个节点,但是这里要注意,就是当队列中只剩下一个节点的时候(这里不包含初始化创建的那个节点),释放了这个节点以后尾指针成了野指针,那么这个时候就要让尾指针和头指针指向同一位置,那么这样判断队列是否为空的时候就是空了。
//链式队列代码 #include <stdlib.h> #include <stdio.h> #include "Queue.h" //初始化队列 void InitQueue(pQUEUE queue) { queue->front = (pNODE)malloc(sizeof(NODE)); queue->front->data = 0; queue->front->pNext = NULL; if (NULL == queue->front) { printf("内存分配失败!\n"); exit(EXIT_FAILURE); } queue->rear = queue->front; } //入队列 void EnQueue(pQUEUE queue, int data) { pNODE p_new = (pNODE)malloc(sizeof(QUEUE)); if (NULL == p_new) { printf("内存分配失败!\n"); exit(EXIT_FAILURE); } p_new->data = data; p_new->pNext = NULL; queue->rear->pNext = p_new; queue->rear = p_new; } //出队列 void DeQueue(pQUEUE queue, int *data) { if (IsEmptyQueue(queue)) exit(EXIT_FAILURE); pNODE p_delete = queue->front->pNext; *data = p_delete->data; queue->front->pNext = p_delete->pNext; if (p_delete->pNext == NULL) queue->rear = queue->front; free(p_delete); p_delete = NULL; } //判断队列是否为空 int IsEmptyQueue(pQUEUE queue) { if (queue->front == queue->rear) return 1; else return 0; } //获得队头元素值 int GetFrontQueue(pQUEUE queue) { int data; if (IsEmptyQueue(queue)) exit(EXIT_FAILURE); data = queue->front->data; return data; } //释放内存 void FreeMemory(pQUEUE queue) { pNODE p_delete = NULL; while (queue->front != NULL) { p_delete = queue->front; queue->front = p_delete->pNext; if (p_delete->pNext == NULL) //如果到达最后一个节点时,队尾指针为NULL queue->rear = NULL; free(p_delete); p_delete = NULL; } }
main.cpp 测试程序——简单的交互界面测试函数功能
#include <stdio.h> #include "Queue.h" int main(void) { int number, i, data, flag; QUEUE q; InitQueue(&q); flag = IsEmptyQueue(&q); if (flag) printf("初始化成功!\n"); printf("请输入入队列个数:"); scanf("%d", &number); for (i=1; i<number+1; i++) { printf("请输入第%d个队点元素值:", i); scanf("%d", &data); EnQueue(&q, data); } DeQueue(&q ,&data); printf("出队列的元素值为:%d\n", data); data = GetFrontQueue(&q); printf("当前栈顶元素值为:%d\n", data); FreeMemory(&q); if (q.front == NULL && q.rear == NULL) printf("内存释放成功!\n"); else printf("内存释放失败!\n"); return 0; }
相关文章推荐
- (C语言版)栈和队列(一)——实现链式栈和链式队列的基本操作以及遇到的问题
- 字符流的基本实现以及编码问题之读操作
- 图的基本操作及BFS与DFS的实现以及飞机换乘问题
- 链式队列的基本操作与实现
- 实验4:栈和队列的基本操作实现及其应用——进制转换以及实验总结
- 【队列】链式结构实现队列的基本操作
- 二叉树遍历非递归算法所用到的栈以及层次遍历所用到的队列的基本操作算法的实现
- 链式队列的基本操作实现c++
- 链队的基本操作实现及约瑟夫环问题的队列解法
- 二叉树的基本操作以及相关问题的求解—C++实现
- 二叉树遍历非递归算法所用到的栈以及层次遍历所用到的队列的基本操作算法的实现
- CAS操作实现并发的优势、以及实现一个无锁队列、怎样解决ABA 问题
- RecyclerView实现瀑布流遇到的各种问题(item移动,加载更多图片闪烁,以及定制各种类型Header和Footer)
- 浅谈spring,基本编程模式和实现原理,以及相关操作流程
- 单链表基本操作以及一些常见的面试问题
- 双链表、链式栈、链式队列 及实现
- 实验4:栈和队列的基本操作实现及其应用之《进制转换》
- 链表的java实现以及基本的增加,删除,排序操作
- 链式栈的基本操作与实现
- 数据结构之队列的基本操作入队出队初始化删除-c++代码实现及运行实例结果