【数据结构 C语言版】 栈与队列

目录

1   顺序栈

顺序栈的创建

1.1   初始化

1.2   判栈空

1.3   判栈满

1.4   进栈

1.5   出栈

1.6   取栈顶

2   双端栈

2.1   初始化

2.2   进栈

2.3   出栈

3   链栈

 链栈的创建

3.1   初始化

3.2   判栈空

3.3   入栈

3.4   出栈

3.5   取栈顶

4   队列

4.1   初始化

4.2   入队

4.3   出队

4.4   取队头


1   顺序栈

栈的定义:作为一种限定性线性表,是将线性表的插入和删除运算限制为仅在表的一段进行。

        表中允许插入和删除操作的一端称为栈顶(Top),表的另一端被称为栈底(Bottom)。

        当栈中没有元素的时候称为空栈。

        栈的插入操作成为进栈和入栈。

        栈的删除操作成为出栈和退栈。

        栈的特点:后进先出。

 

1.1   栈的存储结构:顺序栈和链栈

1.1.1   顺序栈

        用顺序存储结构实现的栈,即利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时由于栈的操作的特殊性,还必须附设一个位置指针 top(栈顶指针)来动态地指示栈顶元素在顺序栈中的位置。

        通常以 top = -1 表示空栈。

 

顺序栈的创建

#define Stack_Size 50
typedef struct
{
	StackElementType elem[Stack_Size];
	int top;
}SeqStack;

栈的基本操作:

        InitStack(S)   初始化:初始化一个新的栈。

        Empty(S)   栈的非空判断:若栈 S 不为空,则返回TRUE;否则,返回FALSE。

        IsFull(S)   栈的非满判断:若栈 S 为满,则返回TRUE;否则,返回FALSE。

        Push(S,x)   入栈:在栈 S 的顶部插入元素 x ,栈满则返回FALSE;否则返回空元素NULL。

        Pop(S)   出栈:若栈 S 不空,则返回栈顶元素,并从栈顶中删除该元素;否则返回空元素NULL。

        GetTop(S)   取栈顶元素:若栈 S 不为空,则返回栈顶元素:否则返回空元素NULL。

        SetEmpty(S)   置栈空操作:置栈 S 为空栈。

1.1   初始化

void InitStack(SeqStack* S)
{
	S->top = -1;
}

1.2   判栈空

bool IsEmpty(SeqStack* S)
{
	return (S->top == -1 ? true : false);
}

1.3   判栈满

bool IsFull(SeqStack* S)
{
	return (S->top == Stack_Size - 1 ? true : false);
}

1.4   进栈

bool Push(SeqStack* S, StackElementType x)
{
	if (S->top == Stack_Size - 1)
	{
		return false
	}
	s->top++;
	S->elem[S->top] = x;
	return true;
}

1.5   出栈

bool Pop(SeqStack* S, StackElementType* x)
{
	if (S->top == -1) 
	{
		return false;
	}
	*x = S->elem[S->top];
	s->top--;
	return true;
}

1.6   取栈顶

bool IntGetTop(SeqStack* S, StackElementType* x)
{
	if (S->top == -1)
	{
		return false;
	}
	*x = S->elem[S->top];
	return true;
}

2   双端栈

当程序里边有多个栈的时候,两栈共享空间。

利用栈,栈底位置不变,栈顶位置动态变化的特点。申请一个共享的一维数组空间 S[M],将两栈的栈底分别放在一维数组的两端,分别为 0,M-1。

 双端栈结构的定义

#define M 100
typedef char StackElementType;
typedef struct
{
	StackElementType Stack[M];
	StackElementType top[2];
}DqStack;

 注意:

        操作时需要表明具体栈(top[0]还是top[1])

        栈空判断

        

         栈满判断 当两个栈迎面相遇才会溢出,即top[0]+top[1]

2.1   初始化

void InitStack(DqStack* S)
{	// 初始化
	S->top[0] = -1;
	S->top[1] = M;
}

2.2   进栈

bool Push(DqStack* S, StackElementType x, int i)
{
	if (S->top[0] + 1 == S->top[1]) return false;
	switch (i)
	{
	case 0:S->top[0]++;
		S->Stack[S->top[0]] = x;
		break;
	case 1:S->top[1]--;
		S->Stack[S->top[1]] = x;
		break;
	default:return false;
	}
	return true;
}

2.3   出栈

bool Pop(DqStack* S, StackElementType* x, int i)
{
	switch (i)
	{
	case 0:if (S->top[0] == -1) return false;
		*x = S->Stack[S->top[0]];
		S->top[0]--;
		break;
	case 1:if (S->top[1] == M) return false;
		*x = S->Stack[S->top[1]];
		S->top[1]++;
		break;
	default:return false;
	}
	return true;
}

3   链栈

一般将链式存储的栈称为链栈,存储结构通常使用单链表。由于栈的特点,只能在栈顶进行插入和删除操作,所以链栈中,通常把单链表的表头做为栈顶,完成压栈,出栈操作。

 链栈的创建

typedef char DataType;
typedef struct snode
{	//链栈的结构体与单链表的结构相同
	DataType data;
	struct snode* next;
}LSNode, * Linkstack;    
//因为不需要头结点,所以要有结构体指针。

3.1   初始化

void InitStack(LinkStack* s)
{	//由于链栈不带头结点,因此只需要将栈顶指针s置空
	*s = NULL;
}

3.2   判栈空

bool IsEmpty(LinkStack s)
{	//只要栈顶指针 s 指向空,栈就是空
	if (s == NULL) return false;
	else
	{
		return true;
	}
}

3.3   入栈

bool Push(LinkStack* s, DataType x)
{	//在栈顶插入 x
	LSNode* p;
	p = (LSNode*)malloc(sizeof(LSNode));
	p->data = x;
	p->next = *s;
	*s = p;
    return true;

}

3.4   出栈

bool Pop(LinkStack* s, DataType* x)
{	//与顺序栈相同,出栈前先判断栈是否为空
	//出站后释放原栈顶
	LSNode* p;
	if (s == NULL)
	{
		printf("栈空!");
		return false;
	}
	p = *s;
	*s = p->next;
	*x = p->data;
	free(p);
	return true;
}

3.5   取栈顶

bool IntGetTop(LinkStack s, DataType* x)
{
	if (s == NULL) return false;
	*x = s->data;
	return true;
}

4   队列

队列是一种只允许在表的一端进行插入操作,而在另一端进行删除操作的星星表。允许插入的一端叫做队尾,允许删除的一端叫队头。当队列没有元素叫做空队列。

每一次入队列的元素都放在原队尾数据元素之后成为新的队尾,每一次出队都是队头元素。

即:先入队的先出队。(先入先出)

 

初始化时,队头指针与队尾指针都指向空,在入队时,队尾指针指向最近入队的元素,队头指针指向第一个元素之前,在出队时,队头指针指向队头元素,队尾指针不变。

我们发现,当队列在出队操作后,在对头指针前空间不能再使用,因此采用循环队列。

 

我们又发现,队空与队满时,都是队头指针==队尾指针。

区分两者有三种办法:

        1,少使用一个空间,当尾指针 rear+1=front 时,认为队满。

        2,设置一个标志位 tag,初始位置 tag=0,入队成功 tag=1,出队成功 tag=0。

                队满条件为:rear==front&tag==1

                队空条件为:rear==front&tag==0

        3,设置计数器 count,初始时设 count=0,每完成入队操作 count++,出队操作 count--。

                队满条件为:count==0

                队空条件为:count==Max

下面采用第三种方法。

循环队列结构的定义

typedef char DateType;
typedef struct
{
	DateType quene[Max];
	int front;	//队头指针
	int rear;	//队尾指针
}SeqQueue;

 队列的基本操作:

        InitQueue(q)   初始化

        InQueue(q,x)   队列 q 尾插元素 x ,成功返回true

        OutQueue(q,x)   删除队首,返回其值,成功返回true

        FrontQueue(q,x)   读对头,队不变

4.1   初始化

void InitQueue(SeqQuene* q)
{
	q->front = 0;
	q->rear = 0;
	q->count = 0;
}

4.2   入队

bool InQueue(SeqQuene* q, DataType x)
{	//入队操作只需要判断是否队满
	if (q->count == Max) return false;
	q->queue[q->rear] = x;
	q->rear=(q->rear+1)%Max;	//队尾指针加 1
	return true;
}

4.3   出队

bool OutQueue(SeqQuene* q, DataType* x)
{	//出队操作只需要判断是否队空
	if (q->count == 0) return false;
	*x = q->queue[q->front];
	q->front = (q->front + 1) % Max;
	return true;
}

4.4   取队头

bool FrontQueue(SeqQuene q, DataType* x)
{
	if (q.count == 0) return false;
	*x = q.queue[q.front];
	return true;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值