栈和队列的基础知识

​ 特点:只能在一个端进行数据的插入和删除,先入栈的数据后出栈,后入栈的数据先出栈。

1.顺序栈

​ 内存空间是连续开辟,长度固定

定义一个描述顺序栈的结构体:

 typedef int datatype;
        typedef struct 
        {
		   datatype *data;//当然这里直接写一个数组也是完全没问题的
		   int len;
		   int top;
		}stack_t;

创建

//1.创建一个空的顺序栈
stack_t *createStack(int len)
{
	//创建一个用于保存栈信息的结构体
	stack_t *p=(stack_t *)malloc(sizeof(stack_t));
	if(NULL == p)
	{
		printf("createStack error.\n");
		return NULL;
	}
	//初始化结构体
	//1.创建栈
	p->data=(datatype *)malloc(sizeof(datatype)*len);
	if(NULL == p->data)
	{
		printf("malloc stack error.\n");
		return NULL;
	}
	p->len=len;

	p->top=-1;//空栈

    return p;
}

,入栈出栈操作

//2.判断栈是否满
int isFullStack(stack_t *p)
{
	return p->len==p->top+1;//1:满  0:非满
}

//3.入栈 
int inStack(stack_t *p,datatype data)
{
	if(isFullStack (p))
	{
		printf("isFullStack error.\n");
		return -1;
	}

	//栈针先移动
	p->top++;

	//数据入栈
	p->data[p->top]=data;
	return 0;
}
//4.判断栈是否为空
int isEmptyStack(stack_t *p)
{
	return p->top == -1;
}

//5.出栈
datatype outStack(stack_t *p)
{
	if(isEmptyStack(p))
	{
		printf("isEmptyStack error.\n");
		return -1;
	}

	return p->data[p->top--];

	//datatype data=p->data[p->top];
	//p->top--;
	//return data;
}

//6.计算栈的长度
int lengthStack(stack_t *p)
{
	return p->top+1;
}
//7.获取栈顶数据
datatype topStack(stack_t *p)
{
	if(isEmptyStack(p))
	{
		printf("isEmptyStack error.\n");
		return -1;
	}

	return p->data[p->top];

}
//8.清空栈
void clearStack(stack_t *p)
{
	p->top=-1;
}
//9.销毁栈 	
void destroyStack(stack_t **sp)
{
	free((*sp)->data);
	free(*sp);
	*sp=NULL;
}

2.链式栈:无头单向链表

特点:内存空间不连续,通过地址连接到一起,长度不固定。

定义节点结构体:

typedef int datatype;
typedef struct node_t
{
	datatype data;
	struct node_t *next;
}lstack_t;

链栈

建立链栈要用头插的方式,因为单链表是单向的,如果尾插的话出栈完最后一个节点,没办法回去了。

另外,入栈出栈后栈针是需要移动的,想要改变值,可以传参传地址或者通过返回值。

//1.创建一个空的无头链式栈 
void createLinkStack(lstack_t **ptop)
{
	*ptop=NULL;
}

//2.入栈
int inLinkStack(lstack_t **ptop,datatype data)
{
	//定义新节点保存入栈的数据
	lstack_t *pnew=(lstack_t *)malloc(sizeof(lstack_t));
	if(NULL == pnew)
	{
		printf("malloc new node error.\n");
		return -1;
	}
	//初始化新建节点
	pnew->data=data;
	pnew->next=*ptop;

	*ptop=pnew; 
    return 0;
}

//3.出栈 
datatype outLinkStack(lstack_t **ptop)
{
	datatype data;
	lstack_t *pdel=*ptop;
	if(isEmptyLinkStack(*ptop))
	{
		printf("isEmptyLinkStack error.\n");
		return -1;
	}

	data=pdel->data;
	*ptop=pdel->next;

	free(pdel);
	pdel=NULL;
	
	return data;
}
//4.判断栈是否为空
int isEmptyLinkStack(const lstack_t *top)
{
	return top == NULL;
}
//5.计算栈的长度
int lengthLinkStack(lstack_t *top)
{
	int len=0;
	while(top != NULL)
	{
       len++;
       top=top->next;
	}
	return len;
}
//6.获取栈顶数据
datatype topLinkStack(lstack_t *top)
{
	if(isEmptyLinkStack(top))
	{
		printf("isEmptyLinkStack error.\n");
		return -1;
	}

	return top->data;
}
//7.清空栈
void clearLinkStack(lstack_t **ptop)
{
	while(!isEmptyLinkStack(*ptop))
	{
		outLinkStack(ptop);
	}
}

或者在主函数里利用返回值修改:

lstack_t *ptop = NULL;
ptop = push(lstack_t *p,datatype x);
ptop = pop(lstack_t *p);

队列

特点:只允许在两端进行插入和删除操作的线性表,
在队尾插入,在队头删除。 插入的一端被称为"队尾",删除的一端被称为"队头"

顺序队列

防止假溢出, 用数组实现队列, 调整“指针”代替队列元素的移动,用取余的方式保证一个循环队列。

特点:内存空间连续开辟,长度固定。

typedef  int  datatype;

	typedef struct 
	{
     datatype  data[N];
     int front;//队头,这里规定指向队头元素的下一个元素
     int rear;//队尾,这里规定指向队尾的下一个元素
	 }seqeue_t;
//队空  
p->rear == p->top
//队满,为了和队空条件区分开,这里浪费一个空间,不能再放数据
(p->rear+1)%N == p->front
//入队
p->data[p->rear]=x;   p->rear = (p->rear+1)%N;
//出队
p->front = (p->front+1)%N
//队中元素个数,加N是为了防止rear小于front,相减是个负数,可以画图看看
(p->rear-p->front +N)%N 

链队:

结构体:

typedef struct link
	{
     datatype data;
     struct link *next;
	 }link_t;
//结构体空间保存信息,next,front,rear指向的类型相同,都是link_t *
typedef struct 
	{
     int len;
     link_t *front;
     link_t *rear;
	 }queue_t;

创建一个空的链式队列

//1.创建一个空的链式队列
queue_t *createLinkQueue(void)
{
	//1)开辟一个保存信息的结构体空间
	queue_t *p=(queue_t *)malloc(sizeof(queue_t));
	if( NULL == p)
	{
		printf("createLinkQueue error.\n");
		return NULL;
	}

	//2)初始化这个结构体
	//1-》创建一个无效头节点,出队的时候很好用
	p->front=p->rear=(link_t *)malloc(sizeof(link_t));
	if(p->front == NULL)
	{
		printf("malloc head node error.\n");
		return NULL;
	}

	//2->初始化节点
	p->front->next=NULL;

	//初始化长度
	p->len=0;
	return p;
}

//入队

int inQueue(queue_t *p,datatype data)
{
	//1.新建节点保存如队的数据
	link_t *pnew=(link_t *)malloc(sizeof(link_t));
	if(NULL == pnew)
	{
		printf("malloc new node error.\n");
		return -1;
	}

	//2.初始化节点 
	pnew->data=data;
	pnew->next=NULL;

	//3.入队
	p->rear->next=pnew;
	p->rear=pnew;

	p->len++;

	return 0;
}

判空

int isEmptyQueue(queue_t *p)
{
	return p->front==p->rear;
}

//3.出队

datatype outQueue(queue_t *p)
{
	if(isEmptyQueue(p))
	{
		printf("isEmptyQueue error.\n");
		return -1;
	}
/*第一次出队的元素是头节点,而不是真正的那个节点,此时它变成了一个无效头节点,队空的时候还剩一个节点。那为什么不让头节点后的那个元素出队呢?这样front会永远指向头节点不动,当p->front->next==NULL的时候,还要让p->rear=p->front,要不然变成野指针了*/
    
    p->rear=q->front的操作。

	link_t *pdel=p->front;
	p->front=pdel->next;
	free(pdel);
	pdel=NULL;
	p->len--;
	return p->front->data;
}

//其他

//5.计算队列的长度
int lenQueue(queue_t *p)
{
	return p->len;
}
//6.清空队列
void clearQueue(queue_t *p)
{
	while(!isEmptyQueue(p))
	{
		outQueue(p);
	}
}
//7.销毁队列
void destroyQueue(queue_t **pp)
{
	clearQueue(*pp);
	free((*pp)->front);
	free(*pp);
	*pp=NULL;
}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值