-
概念
-
定义
栈的所有操作(增删)都必须在栈顶操作,而队列必须在队首删除,在队尾添加。所以如果你要对栈进行操作只需要在一个地方操作,那么栈就可以用顺序表操作,而队列操作完,整个队列的元素都需要移动,所以用链表。定义如下:
//C语言
//这是一个动态栈,即容量满了就自动扩容。
typedef struct Stack
{
int *stack; //数组
int top; //栈顶
int capacity; //容量
}Stack;
typedef struct Queuenode //队列结点
{
int data;
struct Queuenode* next;
}Queuenode;
typedef struct Queue//队首和队尾
{
Queuenode* front;
Queuenode* end;
int size;
}Queue;
//注意队首队尾是Queue,结点是Queuenode
-
操作
-
栈操作
(1) 常规操作。
//C语言
//栈的 初始化
void st_init(Stack* st, int capacity) //首先给一个栈的地址和容量
{
st->capacity = capacity;
st->top = 0;
st->stack = (int*)malloc(sizeof(int) * st->capacity);//申请空间
}
//栈的销毁
void st_destroy(Stack* st)
{
st->stack = NULL; //内容位null
st->capacity = st->top = 0; //容量和栈顶都是0
}
//栈的扩容
void st_capacity(Stack* st) //动态栈的扩容
{
assert(st);//检查是不是空栈
if (st->top = st->capacity) //当栈顶到达了容量就需要扩容
{
printf("栈顶已经达到容量,正在扩容……\n");
st->capacity = st->capacity * 2; //让容量 * 2;
int* newst = (int *)malloc(sizeof(int) * st->capacity);
//定义一个栈的空间保存原始栈的数据
for (int i = 0; i < st->top; ++i)//复制
{
newst[i] = st->stack[i];
}
free(st->stack); //释放旧的内存
st->stack = newst; //新的内存空间
printf("扩容完毕\n");
}
}
//打印栈
void st_print(Stack* st)//遍历,打印
{
for (int i = 0; i < st->top; i++)
{
printf("%d -> ",st->stack[i]);
}
printf("top\n");
}
(2)进阶操作
//C语言
//栈的插入
void st_add(Stack* st,int data)
{
if (st->top == st->capacity)
{
st_capacity(st); //如果容量不足扩容
}
st->stack[st->top] = data;
++st->top; //在栈顶添加一个元素,栈顶加一
}
//栈的删除
void st_del(Stack* st)
{
assert(st); //断言是判断是否有这个栈的地址
if (st->top == 0)
{
return; //空栈栈不能删
}
--st->top;//top 减一就好
}
//输出栈顶元素
int st_topdata(Stack* st)
{
return st->stack[st->top-1];//数组下标从零开始。top从1开始
}
//求栈的有效长度
int st_size(Stack* st)
{
return st->top ;
}
//判断是否为空
int st_empty(Stack* st)
{
if (st->top == 0)
{
return 0; //0为空
}
return 1;
}
-
队列操作
(1)基础操作
//C语言
//队列的初始化
void qu_init(Queue* qu)
{
assert(qu);
qu->front = qu->end = NULL;
qu->size = 0;
}
//队列的销毁
void qu_destroy(Queue* qu)
{
assert(qu);
Queuenode* temp;
for (Queuenode* cur = qu->front; cur != NULL; cur = temp)
{
temp = cur->next;//销毁需要从队首开始走到队尾,释放每个结点
free(cur);
}
qu->front = qu->end = NULL;
qu->size = 0;
}
//打印队列
void qu_print(Queue* qu) //从队首开始打印队列
{
assert(qu);
Queuenode* temp = qu->front;
if (temp == NULL)
{
printf("无队列\n");
return;
}
printf("front = ");
while (temp != NULL)
{
printf("%d => ",temp->data);
temp = temp->next;
}
printf("end\n");
}
(2)进阶操作
//C语言
//获取结点
Queuenode* qu_getnode(int data)//给插入做准备
{
Queuenode* node;
node = (Queuenode*)malloc(sizeof(Queuenode));
node->data = data;
node->next = NULL;
return node;
}
//队列的插入
void qu_add(Queue* qu, int data)
{
Queuenode* node = qu_getnode(data);
if (qu->end == NULL) //如果是空队列
{
qu->front = qu->end = node;
}
else
{
qu->end->next = node;//在队尾进行插入
qu->end = node;
}
++qu->size;//队列长度加一
}
//队列的删除
void qu_del(Queue* qu)
{
assert(qu);
Queuenode* delnode = qu->front; //保存队首
qu->front = qu->front->next;//队首指针后移
free(delnode);//释放队首
if (qu->front == NULL)
{
qu->end = NULL;//这是只有一个结点的情况
}
--qu->size;
}
//求队列队首
void qu_frontnode(Queue* qu)
{
printf("front == %d\n",qu->front->data);
}
//求队列队尾
void qu_endnode(Queue* qu)
{
printf("end == %d\n",qu->end->data);
}
//判断队尾为空
void qu_empt(Queue* qu)
{
if (qu->size == 0)
{
printf("队列为空\n");
}
else
{
printf("队列有 %d 个元素\n",qu->size);
}
}
//队列的长度
int qu_size(Queue* qu)
{
return qu->size;
}
- assert
代码里出现了很多断言assert();这是为了判断传入的地址是否有效。不是判断队列或栈是否为空。