前言
也是数据结构的学习。栈和队列很相似,所以我就用C语言一起实现它们(毕竟不会c++),毕竟写完一个就可以说另一个也基本上写完了。当然我说的学习是理解,关于代码的参考修正与美化,都是在网上找的。
关于实现栈与队列
栈和队列都是用带表头的单链表实现的,因为也没学过单链表,所以在实现栈与队列之前去学了下单链表,可以说现在学了一半的栈,一半的队列,一般的链表。
栈——先进后出
Push
用结构体开一个链表表头,表头不存数据,目前表头里的指针指向NULL:
栈 | Head_Stack |
---|---|
数据 | - |
指向的栈 | Stack_1 |
入栈就是把栈插进表头的后面,并读入栈所要储存的数据(假定为1):
栈 | Head_Stack | Stack_1 |
---|---|---|
数据 | - | 1 |
指向的栈 | Stack_1 | NULL |
假设新栈为Stack_New,要存储数字3:
栈 | New_Stack |
---|---|
数据 | 3 |
插入的结果就是:
栈 | Head_Stack | New_Stack | Stack_1 |
---|---|---|---|
数据 | - | 3 | 1 |
指向的栈 | New_Stack | Stack_1 | NULL |
以此类推即可让栈一堆再堆
GetTop
每次要提取的栈即最顶上的栈,肯定就是Head_Stack所指向的栈,所以只要栈不空,返回所存储的值即可。
Pop
跟GetTop里说的一样,先把该栈之后的栈和Head_Stack连接,再弹出该栈即可。
关于其它函数
- InitStack:创建栈
- ClearStack:把栈清空
- DestroyStack:把栈消灭
- StackEmpty:检测栈是否为空
- StackLength:检测栈目前的长度
代码实现
用一个stack.h的自制头文件装起来,方便以后使用。
#ifndef __STACK_H__
#define __STACK_H__
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//创建链表,定义元素类型
typedef int TypeData;
typedef struct node {
TypeData data;
struct node* next;
}Stack;
//判断栈是否为空,为空返回1,不为空返回0
int StackEmpty(Stack* stack)
{
return stack->next == NULL;
}
//创建栈,成功返回栈,失败返回NULL
Stack* InitStack()
{
Stack* H_stack = (Stack*)malloc(sizeof(Stack));
if (H_stack != NULL)
{
H_stack->next = NULL;
return H_stack;
}
return NULL;
}
//弹出栈,成功返回1,失败返回0
int Pop(Stack* stack)
{
if (!StackEmpty(stack))
{
Stack* temp_stack = stack->next;
stack->next = temp_stack->next;
free(temp_stack);
return 1;
}
return 0;
}
//提取栈,成功返回data的值,失败返回-1
TypeData GetTop(Stack* stack)
{
if (!StackEmpty(stack))
{
return stack->next->data;
}
return EOF;
}
//放入栈,成功返回,失败返回0
int Push(Stack* stack, TypeData data)
{
Stack* new_stack = (Stack*)malloc(sizeof(Stack));
if (new_stack != NULL)
{
new_stack->data = data;
new_stack->next = stack->next;
stack->next = new_stack;
return 1;
}
return 0;
}
//清空栈,如果已经是空栈则返回1,不然返回0
int ClearStack(Stack* stack)
{
while (!StackEmpty(stack))
{
Pop(stack);
}
if (StackEmpty(stack))
{
return 1;
}
return 0;
}
//我觉得破坏栈之前还是先把栈清空要好一点,破坏成功返回1,否则返回0
int DestroyStack(Stack* stack)
{
if (ClearStack(stack))
{
free(stack);
return 1;
}
return 0;
}
//顺藤摸瓜法求计算栈目前的长度(元素数目),最后返回n,没有栈则返回0
int StackLength(Stack* stack)
{
int n;
Stack* test_stack;
for (n = 0, test_stack = stack; test_stack->next != NULL; test_stack = test_stack->next, n++);
return n;
}
#endif
以上就是关于栈的内容。
队列——先进先出
与栈的不同
队列与栈很相似,只不过插入元素时并非在队头之后插入,而是在队列的末尾插入。队列里的都是文明人,如果说栈也是队列的话,那就是只会插队的莽夫。
名称上的不同
数据类型 | 栈 | 队列 |
---|---|---|
插入 | Push | EnQueue |
弹出 | Pop | DeQueue |
提取 | GetTop | GetHead |
创建 | InitStack | InitQueue |
清空 | ClearStack | ClearQueue |
销毁 | DestroyStack | DestroyQueue |
计算长度 | StackLength | QueueLength |
判断是否为空 | StackEmpty | QueueEmpty |
所作修改
为了实现在队尾插入元素,还需要一个指针来指向队尾。
我把结构体的next换成了front与back,front指向前一个元素,back指向后一个元素,而队头的front指向队尾元素,队尾元素的back为NULL。
代码实现
还是用一个queue.h存起来
#ifndef __QUEUE_H__
#define __QUEUE_H__
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef int TypeData;
typedef struct node {
TypeData data;
struct node* front;
struct node* back;
}Queue;
int QueueEmpty(Queue* queue)
{
return queue->back == NULL;
}
Queue* InitQueue()
{
Queue* head_queue = (Queue*)malloc(sizeof(Queue));
if (head_queue != NULL)
{
head_queue->back = NULL;
head_queue->front = head_queue;
return head_queue;
}
return NULL;
}
int DeQueue(Queue* queue)
{
if (!QueueEmpty(queue))
{
Queue* temp_queue = queue->back;
queue->back = temp_queue->back;
free(temp_queue);
return 1;
}
return 0;
}
TypeData GetHead(Queue* queue)
{
if (!QueueEmpty(queue))
{
return queue->back->data;
}
return EOF;
}
int EnQueue(Queue* queue, TypeData data)
{
Queue* new_queue = (Queue*)malloc(sizeof(Queue));
if (new_queue != NULL)
{
new_queue->data = data;
new_queue->front = queue->front;
new_queue->back = queue->front->back;
queue->front->back = new_queue;
queue->front = new_queue;
return 1;
}
return 0;
}
int ClearQueue(Queue* queue)
{
while (!QueueEmpty(queue))
{
DeQueue(queue);
}
if (QueueEmpty(queue))
{
return 1;
}
return 0;
}
int DestroyQueue(Queue* queue)
{
if (ClearQueue(queue))
{
free(queue);
return 1;
}
return 0;
}
int QueueLength(Queue* queue)
{
int n;
Queue* test_queue;
for (n = 0, test_queue = queue; test_queue->back != NULL; test_queue = test_queue->back, n++);
return n;
}
#endif
我的想法
队列我既然加了个front的指针,那么理应可以实现循环队列,优先队列,双向队列之类的东西,但是,再说再说orz…
以上就是关于队列的内容