1.栈和队列基本概念
在数组中,我们可以通过索引(下标)随机访问元素。但是,在某些情况下,外面可能需要限制处理顺序,这就产生了栈和队列这两种功能受限的线性结构。
栈(stack)
先进后出:LIFO(last in first out)
栈只有一个开口,先进去的就到下面,后进来的就在上面(top),要是拿出去的话,肯定是先从开口段拿出去,所以说
队列(queue)
先进先出:FIFO(first in first out)
队列中有队首(front)和队尾(back),队首指向队列的第一个数据,队尾指向队列的最后一个数据。数据从队尾入队,从队首出对。
2.栈和队列的功能实现
1.栈的基本操作:增、删、查、改。
栈的结构可以用数组或者链表实现。
1.栈结构的声明
typedef int Type;
#define STACK_SIZE 10//栈的最大大小
/*顺序栈结构的声名*/
typedef struct Stack
{
Type data[STACK_SIZE];//栈的数据域
int top;//栈顶元素下标
}stack;
2.栈的初始化
使用malloc动态开辟一个stack大小的内存
初始化栈顶的元素下标
stack* stack_init()
{
stack* temp = (stack*)malloc(sizeof(stack));
/*if (NULL == temp)
{
printf("初始化栈失败!\n");
return NULL;
}*/
assert(temp);//断言(报错)函数(来自断言头文件):
//当函数参数为NULL或者0时会断言(中断程序执行并弹出报错窗口)
temp->top = -1;//初始化栈顶元素下标top值为-1(-1表示栈中没有数据,栈为空)
}
3.栈的创建
见上
4.数据入栈
void stack_push(stack* st, Type val)
{
assert(st);//判断栈是否存在
assert(!stack_full(st));//判断栈是否满
st->data[++st->top] = val;//向栈顶插入数据
}
5.数据出栈
数据出栈需要取出栈顶的元素,所以要将元素下标top作自减
Type stack_pop(stack* st)
{
assert(st);//判断栈是否存在
assert(!stack_empty(st));//判断是否空
return st->data[st->top--];//返回栈顶元素
}
6.获取栈顶元素
获取元素但不出栈,和数据出栈的差距是不需要作自减操作
Type stack_top(stack* st)
{
assert(st);//判断栈是否存在
return st->data[st->top];//返回栈顶元素
}
7.判断栈空
int stack_full(stack* st)
{
//if (st->top >= STACK_SIZE - 1);
//return 1;//栈满
//return 0;//栈没满
return st->top >= STACK_SIZE - 1;
}
8.判断栈满
int stack_empty(stack* st)
{
return st->top==-1;//如果栈为空则返回非0值(返回1),否则返回0
}
2.队列的基本操作:增删查改
1.队列结构体的声明
typedef int Type;
typedef struct node {//链队节点结构体的声明
Type data;//数据域
struct node* next;//指针域
}Node;
typedef struct queue {//整个链队的结构声明
Node* front;//队首指针
Node* front;//队尾指针
}Queue;
//队列的功能声明
2.队列的初始化
Queue* queue_init()
{
Queue* temp = (Queue*)malloc(sizeof(Queue));
assert(temp);
temp->front = temp->back = NULL;//队首和队尾创建并初始化为空
return temp;
}
3.队列的创建
Node* node_create(Type val)
{
Node* temp = (Node*)malloc(sizeof(Node));
assert(temp);
temp->data = val;
temp->next = NULL;
return temp;
}
4.数据入队
void queue_push(Queue* q, Type val)
{
assert(q);
if (NULL == q->front)
{
//队列中只有一个节点,此节点既是队首也是队尾
q->front = q->back = node_create(val);
}
else
{
q->back = q->back->next = node_create(val);
//创建新节点并连接上链表尾部,新节点成为新的尾部
}
}
5.数据出队
Type queue_pop(Queue* q)
{
assert(q);
assert(q->front);
Node* temp = q->front;//记录被删除节点的位置
Type val = temp->data;//记录被删除节点的数据
q->front = q->front->next;//队首节点的下一个节点成为新的队首
free(temp);//释放原来的队列
temp = NULL;//防止野指针
return val;
}
6.获取队首元素
Type queue_front(Queue* q)
{
assert(q);//判断整个链表是否存在
assert(q->front);//判断链表是否为空
return q->front->data;//返回队首元素
}
7.获取队尾元素
Type queue_back(Queue* q)
{
assert(q);//判断整个链表是否存在
assert(q->back);//判断链表是否为空
return q->back->data;//返回队尾元素
}