欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 数据结构:栈

数据结构:栈

2025/2/23 19:41:03 来源:https://blog.csdn.net/2301_80744520/article/details/141280782  浏览:    关键词:数据结构:栈

1、栈的表示

顺序栈的表示

存储方式:利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。

栈底一般在低地址。

top:指示栈顶元素位置

base:指示栈底元素位置

stacksize:表示栈的最大容量

接下来,我们用更详细的一幅图来描述顺序栈:

起始状态,top和base都指向0的位置,此时是空栈:base==top,且栈的容量stacksize=4。

接下来为空的栈添加元素(入栈),将新的元素添加到top所指位置,再将top移向下一位置,我们最终可以观察到top并没有指向D,而是栈的外面,即4的位置。

因此栈的容量stacksize=top-base。

注意:top的最初指向位置是人为规定的,可以指向-1,也可以指向0,具体根据题目判断。

接下来,外面根据代码加深对顺序栈的理解:

typedef struct
{SELemType* base;//栈底指针SELemType* top;//栈顶指针int stacksize;//栈可用最大容量
}sqStack;
sqStack S;//定义了一个名为S的顺序栈

根据代码,我们首先定义了一个顺序栈的结构体类型,包括栈底指针和栈顶指针,同时包含栈的容量。接着创建了一个S的顺序栈。

2、顺序栈的实现

2.1初始化

Status InitStack(SqStack& S)
{S.base = new SElemType[MAXSIZE];if (!S.base){return OVERFLOW;//空间分配失败}S.top = S.base; //栈顶指针=栈底指针S.stackSize = MAXSIZE;return OK;
}

这串代码的功能就是创建了一个顺序栈,并对顺序栈初始化,使top和base都指向0的位置。

2.2入栈

入栈的含义就是在原有的栈中插入新的元素。我们把新的元素插入在栈顶指针的位置。因此需要经历下面几个步骤:

1、判断是否栈满,栈满就无法进行插入了。

2、栈顶指针指向要插入的元素,并将栈顶指针移向下一位置。

通过图示,大家可以进一步理解上述步骤。

基于前面创建好的顺序栈,我们就可以用代码实现入栈:

Status Push(SqStack& S, SElemType)
{if (S.top - S.base == S.stacksize)//判断栈满return ERROR;*S.top = e;//栈顶指针top指向的元素为eS.top++;//将栈顶指针移向下一位置
}

2.3出栈

出栈可以理解为从栈顶移除一个元素,有以下步骤:

1、判断是否栈空,栈空就不能移除元素。

2、栈顶指针往下移动,再将所指元素赋给e。

通过图示,我们可以进一步理解:

Status Pop( SqStack &S, SElemType e) 
{
if( S.top == S.base) // 栈空return ERROR; 
--S.top;
e=*S.top;
return OK;
}

3、链栈的表示与实现

3.1链栈的表示

我们可以类比顺序表与链表的关系理解链栈的概念。与链表不同的是链栈没有头指针的,栈顶指针就是链表的头指针。同时每一项包含数据域和指针域,指针域指向下一个元素的地址。

typedef struct StackNode 
{int data;//数据域struct StackNode* next;//指针域
}stackNode, * LinkStack;
LinkStack S;

3.2链栈的实现

3.2.1初始化

由于链栈不需要头节点,我们基于创建好的链栈,使栈顶指针指向空即可。

void initStack(LinkStack& s)
{s = NULL;//不需要头节点
}

3.2.2判空

根据链栈初始化的内容,我们可以根据栈顶指针指向的内容判断是否为空。

int stackEmpty(LinkStack s)
{if (s == NULL)return ok;return error;
}

3.2.3求链栈长度

与顺序栈不同,链栈的元素是随机存放的,无法根据top-base的方法得到长度。因此,我们需要设置一个计数器,通过边累加,边让栈顶指针往下移动,直到指向空停止循环,得出链栈的长度。 

int stackLength(LinkStack s)
{int sum = 0;stackNode* temp = s;while (temp != NULL){sum++;temp = temp->next;}return sum;
}

3.2.4入栈

入栈可以类比在链表中插入元素。我们根据代码做进一步解释。 

void push(LinkStack& s, int e)
{stackNode* p = new stackNode;p->data = e;//创建一个包含数据域和指针域的项p->next = NULL;if (s == NULL)//将问题分为两种情况s = p;//s指针指向pelse{p->next = s;//p指针的前驱指向ss = p;//s指针指向p}
}

首先我们创建一个包含数据域和指针域的项并用P指向它。接着分情况讨论,如果链表为空,那么指针s 直接指向p,如果不为空则让p的后继指向s,再将s挪至p的位置。

3.2.5出栈

出栈可以类比在链表中删除元素。我们根据代码做进一步解释。

void pop(LinkStack& s, int& e)
{stackNode* p = new stackNode;if (s == NULL)//如果链栈为空则无法出栈{cout << "栈为空" << endl;}else{p = s;//用p记录指针s的位置e = p->data;//将指针s指向的元素赋值给es = s->next;//将s移至下一位置delete p;//删除pcout << "成功弹出栈顶元素" << endl;}
}

首先判断是否为空栈,如果是空栈则无法移除元素。如果不是空栈我们创建指针p用于记录s的位置,并将指针s指向的元素赋给e。接着我们将s挪至s的后继,再将p删除即可实现出栈操作。 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词