数据结构——栈和队列

  • 概念

      

  •  定义

     栈的所有操作(增删)都必须在栈顶操作,而队列必须在队首删除,在队尾添加。所以如果你要对栈进行操作只需要在一个地方操作,那么栈就可以用顺序表操作,而队列操作完,整个队列的元素都需要移动,所以用链表。定义如下:

//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();这是为了判断传入的地址是否有效。不是判断队列或栈是否为空。

欢迎评论区留言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值