栈与队列 -- 增、查、改、删操作

版权声明:转载请标注博主个人主页:http://blog.csdn.net/ViatorSun 及本篇博客地址 https://blog.csdn.net/ViatorSun/article/details/82917094

1. 栈

栈是一种只能在一端进行插入或删除操作的线性表
其中允许进行插入或删除操作的一端称为栈顶(Top)
栈顶由一个栈顶指针的位置指示器(其实是1个变量,对于顺序栈就是记录栈顶元素所在数组位置标号的一个整型变量,对于链式栈就是记录栈顶元素所在结点地址的指针)它是动态变换的。
表的另一端称为栈底,栈底是固定不变的。
栈的插入和删除操作一般称为入栈和出栈。
特点:先进后出(FILO)
存储结构:顺序栈和链式栈
栈是一种在操作上稍加限制的线性表,即栈的本质是线性表;
数学性质:
当n个元素以某种顺序进栈,并且可在任意时刻出栈时,所获得的元素排序的数目N恰好满足函数

N = 1 n + 1 C 2 n n N=\frac{1}{n+1}C_{2n}^{n}

01. 顺序栈

栈空状态:st.top == -1或st.top == 0
栈满状态:st.top ==maxsize -1

因为数组下标从0开始,maxsize -1 为栈满时,栈顶元素在数组中的位置

上溢:栈满继续入栈
下溢:栈空的时候继续出栈所造成的

元素x进栈操作:

++(st.top);
st.data[st.top]=x ;

必须先移动指针,再进入元素
元素x出栈操作:

x = st.data[st.top] ;
--(st.top);

1) 定义栈

typedef  struct
{
	int  data[maxsize];
	int  top;
}SqStack;

2) 初始化栈

void  initStack( SqStack  &st)
{
	st.top = -1;
}

3) 判断栈空

int  isEmpty(SqStack  st)
{
	if(st.top  ==-1)
		return  1;
	else
		return  0;
}

4) 进栈

int  push(SqStack  &st , int x)
{
	if(st.top == maxsize -1)
		return  0;

	++(st.top);
	st.data[st.top] = x;
		return  1;
}

5) 出栈

int  pop(SqStack &st ,int &x)
{
	if(st.top == -1)
		return  0;

	x = st.data[st.top];
	--(st.top);
	return  1;
}

6) 简化操作

//定义并初始化
int  stack[maxsize];
int  top = -1;


//元素x进栈
stack[++top] == x;

//元素x出栈
x = stack[top--];

02、 链栈

栈空状态:lst->next == NULL;
栈满状态:不存在栈满状态
元素进栈(由p指针所指)

	p->next = lst->next;
	lst->next = p

元素出栈(出栈元素保存在x中)

	p = last->next;
	x = p->data;
	lst->next = p->next;
	free(p)

1) 链栈结点定义

typedef  struct  LNode
{
	int  data;
	struct  LNode *next;
}LNode;

2) 初始化链栈

void  initStack(LNode  *&lst)
{
	lst = (LNode *)malloc(sizeof(LNode));
	lst->next = NULL;
}

3) 判断栈空

int  isEmpty(LNode  *lst)
{
	if(lst->next == NULL)
		return 1;
	else 
		return 0;
}

4) 进栈(头插法)

void  push(LNode *lst , int x)
{
	LNode  *p;
	p = (LNode *)malloc(sizeof(LNode));
	p->next = NULL;

	p->data = x;
	p->next = lst->next;
	p->next = p;
}

5) 出栈

int  pop(LNode *lst , int &x)
{
	LNode  *p;
	if(lst->next == NULL)
		return 0;
	p = lst->next;
	x = p->data;
	lst->next = p->next;
	free(p);
	return  1;
}

3. 队列

定义:队列是一种操作受限的线性表, 其限制为仅允许在标的一端进行插入,在表的另一端删除, 可进行插入的一端称为队尾,可进行删除的一端称为队头; 向队列中插入元素称为进队,新元素进队后就成为新的队尾元素; 从队列中删除元素称为出队,其后继元素就成为新的队头元素。

扫描二维码关注公众号,回复: 4977179 查看本文章
  • 特点:
    先进先出(FIFO)
  • 存储结构:
    可用顺序表和链表来存储队列,分别为顺序队、链队

01. 顺序队列

假溢出问题:

  1. 队尾指针rear -> 刚进队元素位置
  2. 队首指针fort -> 刚出队元素位置
  3. 进队时 rear 向后移动
  4. 出队时 fort 向后移动

这样进过一系列的出队和进队操作之后,两个指针最终会到达数组末端,maxsize-1处,队中没有元素,但仍然无法进队,这就是“假溢出问题”

解决办法:

将数组组成一个环,让rear和fort沿着环走,这样就产生了循环队列,可以通过执行语句 fort = (fort +1)%maxsize 实现环形道路走。

队满:

(rear+1)%maxsize == fort   :  (qu.rear+1)%maxsize == qu.fort

队空:

fort == rear

元素x进队(移动队尾指针):元素入队时,先移动指针,后存入元素

qu.rear = (qu.rear + 1)%maxsize;
qu.data[qu.rear] = x;

元素x出队(移动队首指针):元素出队时,先移动指针,再取出元素

qu.fort = (qu.fort +1)%maxsize;
x = qu.data[qu.fort];

1) 初始化队列

void  initQueue(SqQueue  &qu)
{
	qu.fort = qu.rear = 0;
}

2) 判断队空

init  isQueueEmpty(SqQueue  qu)
{
	if(qu.fort  ==  qu.rear)
		return  1;
	else
		return  0;
}

3) 进队算法

init  enQueue(SqQueue  &qu , int x)
{
	if((qu.rear+1)%maxsize == qu.fort)
		return  0;

	qu.rear = (qu.rar+1)%maxsize;
	qu.data[qu.rear] = x;
	return  1;
}

4) 出队算法

int  deQueue(SqQueue  &qu , int &x)
{
	if(qu.fort == qu.rear)
		return  0;
	qu.fort = (qu.fornt+1)%maxsize;
	x = qu.data[qu.fornt];
	return  1;
}

02. 链队

链队就是采用链式存储结构存储队列(这里采用单链表实现)

  • 特点:不存在队列满上溢的情况
    队空状态:lqu ->rear == NULL 或 lqu -> fort == NULL
    队空状态:不存在这种情况
    元素进队操作:(假设p指向进队元素)
lqu->rear->next  =  p; 
lqu->rear  =  p;

元素出队操作:(假设x存储出队元素)

p  =  lqu->fort;
lqu->fort = p->next;
x = p->data;
free(p);

1) 链队类型定义

typedef  struct
{
	QNode  *fornt;
	QNode  *rear;
}LiQueue;

2) 初始化链队

void  initQueue(LiQueue  *&lqu)
{
	lqu = (LiQueue *)malloc(sizeof(LiQueue));
	lqu->fornt  =  lqu->rear  =  NULL;
}

3) 判断队空

int  isQueueEmpty(LiQueue  *lqu)
{
	if(lqu->rear  ==  NULL  ||  lqu->fort  ==  NULL)
		return  1;
	else
		return  0;
}

4) 入队算法

void  enQueue(LiQueue  *lqu , int  x)
{
	QNode  *p;
	p  =   (QNode *)malloc(sizeof(QNode));
	p->data  =  x;
	p->next  NULL;
	if(lqu-rear  ==  NULL)
		lqu->fornt  =  lqu->rear  =  p;
	else
	{
	lqu->rear->next  =  p;
	lqu->rear  =  p;
}
}

5) 出队算法

int  deQueue(LiQueue  *lqu , int  &x)
{
	QNode  *p;
	if(lqu->rear  ==  NULL)
		return  0;
	else
		p  =  lqu->fornt;
	if(lqu->fornt  ==  lqu->rear)
		lqu->fornt  =  lqu->rear  =  NULL;
	else
		lqu->fornt  =  lqu->fornt->next;
	x  =  p->data;
	free(p)
	return  1}

猜你喜欢

转载自blog.csdn.net/ViatorSun/article/details/82917094