‘壹’ 链式栈的栈顶元素是最后输入的元素吗
首先,需要知道数据结构栈的特点,是先进后出或者说是后进先出。
回到你的问题上,看你怎么理解最后输入的元素吧。对于我的理解是,尽管栈顶元素有可能出现出栈的情况,无论是否出现出栈,出栈后的元素就不算栈中的数据,此时栈顶元素必定就是最后输入的元素。
‘贰’ 链栈中为什么需要头结点
链栈中需要头结点原因:因为栈是后进先出的数据结构,我们不可能直接就对栈底元素进行操作,要想操作栈底元素,必须得先依次让非栈底元素出栈。
即使设了头指针,也没有用处,对栈顶元素的操作,与头指针没关系。所以不必设头指针指向栈底元素。
1、头结点不存储数据,此时它只是个标记。链表从这里开始,意义在于头结点中的next。引出后面的链表数据。这就是平常写的头结点。
2、头结点存储数据,它此时就不只是个标记和引出后面的链表数据,还有它里面的data。意义在于data 和 next。
两个栈共享同一存储空间:
当程序中同时使用两个栈时,可以将两个栈的栈底设在向量空间的两端,让两个栈各自向中间延伸。当一个栈里的元素较多,超过向量空间的一半时,只要另一个栈的元素不多,那么前者就可以占用后者的部分存储空间。
只有当整个向量空间被两个栈占满(即两个栈顶相遇)时,才会发生上溢。因此,两个栈共享一个长度为m的向量空间和两个栈分别占用两个长度为└m/2┘和┌m/2┐的向量空间比较,前者发生上溢的概率比后者要小得多。
‘叁’ 栈是不是顺序存储的线性结构啊
不一定。
栈分顺序栈和链式栈。顺序栈为栈的顺序实现,顺序栈为利用顺序存储结构实现的栈。
采用地址连续的存储空间(数组)依次存储栈中数据元素,由于人栈和出栈运算都是在栈顶进行,而栈底位置是固定不变的,可以将栈底位置设置在数组空间的起始处;栈顶位置为随入栈和出栈操作而变化的,故需用一个整型变量top来记录当前栈顶元素在数组中的位置。
链式栈为一种数据存储结构,可以通过单链表的方式来实现,使用链式栈的优点在于它能够克服用数组实现的顺序栈空间利用率不高的特点,但是需要为每个栈元素分配额外的指针空间用来存放指针域。
(3)链式栈的栈底元素缓存数据吗扩展阅读
栈作为一种数据结构,为一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。
在计算机系统中,栈为一个具有以上属性的动态内存区域。程序可以将数据压入栈中,也可以将数据从栈顶弹出。在i386机器中,栈顶由称为esp的寄存器进行定位。压栈的操作使得栈顶的地址减小,弹出的操作使得栈顶的地址增大。
‘肆’ 链栈的栈顶和栈底是什么
这些都是数据结构中的知识。堆栈的特征是先入后出,而不是队列先入先出。堆栈的顶部是最后一个推入的元素,是链的末端,堆栈的底部是第一个推入的元素,是链的末端。
在创建线程时,堆栈是内存中的一个快速空间,用于处理函数被调用时生成的临时变量,以及当前正在执行的函数(调用函数号)的地址。当被调用的函数在运行后返回时,程序继续从保存在那里的地址执行。
栈采用后进先出的数据存储方式。底部的堆栈栈存储变量的起始地址,和堆栈指针的地址指向当前的存储数据,当你推到堆栈数据,根据数据类型,字节的堆栈指针是上升的反应(如数据存储类型,移动第四节单词让),堆栈指针指向四个字节后的内存地址。
(4)链式栈的栈底元素缓存数据吗扩展阅读:
事实上,链堆栈也是链表的一种形式。头指针总是指向表的第一个节点(或头节点),而顶部指针总是指向堆栈的顶部。在创建链表时,通常有两种插补方法:一种是头插补方法,另一种是尾插补方法。
链栈是相同的,假设所创建的栈没有头节点,即第一个节点开始存储数据,按照头节点插入的方法来构建栈,头指针是顶部指针,两者之间没有区别;当使用尾部插入方法构建堆栈时,头指针不是堆栈的顶部指针。
在这种情况下,应该定义一个尾部指针,以始终指向堆栈的最后一个元素(即要推入堆栈的最后一个元素),以便尾部指针是堆栈的顶部指针。
‘伍’ 链栈和顺序栈两种存储结构有什么不同
存储结构不同:
链栈动态分配内存存储数据,不浪费内存,存储的数据不连续。
顺序栈使用固定大小数组保存数据,数据量小时浪费内存,过多时出问题,存储数据连续。
它们的具体区别如下:
顺序栈的实现在于使用了数组这个基本数据结构,数组中的元素在内存中的存储位置是连续的,且编译器要求我们在编译期就要确定数组的大小,这样对内存的使用效率并不高,一来无法避免因数组空间用光而引起的溢出问题。在系统将内存分配给数组后,则这些内存对于其他任务就不可用。而对于链栈而言,使用了链表来实现栈,链表中的元素存储在不连续的地址,由于是动态申请内存,所以我们可以以非常小的内存空间开始,另外当某个项不使用时也可将内存返还给系统。
‘陆’ 解释一下C++中链表和链栈的功能和编程思想
链表 是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
线性表的链式存储表示的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素 与其直接后继数据元素 之间的逻辑关系,对数据元素 来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。由这两部分信息组成一个"结点"(如下图所示),表示线性表中一个数据元素 。
数据域 data 指针域 next
其中存储数据元素信息的域称作数据域(设域名为data),存储直接后继存储位置的域称为指针域(设域名为next)。指针域中存储的信息又称做指针或链。
由分别表示,,…, 的N 个结点依次相链构成的链表,称为线性表的链式存储表示,由于此类链表的每个结点中只包含一个指针域,故又称单链表或线性链表.
=====================================================
三个链表函数(c++)
#include <stdio.h>
#include <stdlib.h>
struct Node{
int data;
Node * next;
};
void insert(Node * root,int idx,int d){
Node * tmp = root;
for(int i = 0;i<idx;i++){
tmp = tmp->next;
if(tmp == NULL) return ;
}
Node * tmp2 = new Node;
tmp2->data = d;
tmp2->next = tmp->next;
tmp->next = tmp2;
}
int del(Node * root,int idx){
Node * tmp = root;
for(int i = 0;i<idx;i++){
tmp = tmp->next;
if(tmp == NULL) return -1;
}
int ret = tmp->next->data;
tmp->next = tmp->next->next;
return ret;
}
void print(Node * root){
for(Node *tmp = root; tmp!=NULL; tmp = tmp->next)
printf("%d ",tmp->data);
printf("\n");
}
int main(){
Node * root;
root = new Node;
root->data = -1;
return 0;
}
链栈,可能你是说错了,
应该是采用链式存储的栈,
栈(stack)在计算机科学中是限定仅在表尾进行插入或删除操作的线形表。
栈是一种数据结构,它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。
栈是只能在某一端插入和删除的特殊线性表。用桶堆积物品,先堆进来的压在底下,随后一件一件往堆。取走时,只能从上面一件一件取。堆和取都在顶部进行,底部一般是不动的。
栈就是一种类似桶堆积物品的数据结构,进行删除和插入的一端称栈顶,另一堆称栈底。插入一般称为进栈(PUSH),删除则称为退栈(POP)。 栈也称为后进先出表(LIFO表)。
1、进栈(PUSH)算法
①若TOP≥n时,则给出溢出信息,作出错处理(进栈前首先检查栈是否已满,满则溢出;不满则作②);
②置TOP=TOP+1(栈指针加1,指向进栈地址);
③S(TOP)=X,结束(X为新进栈的元素);
2、退栈(POP)算法
①若TOP≤0,则给出下溢信息,作出错处理(退栈前先检查是否已为空栈, 空则下溢;不空则作②);
②X=S(SOP),(退栈后的元素赋给X);
③TOP=TOP-1,结束(栈指针减1,指向栈顶)。
‘柒’ 栈和队列不是逻辑结构吗,它们的顺序和链式才是存储结构,一题中说栈也是存储结构,请解释一下
栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。
(7)链式栈的栈底元素缓存数据吗扩展阅读:
栈的顺序存储结构利用内存中的一片起始位置确定的连续存储区域来存放栈中的所有元素,为了指示栈顶的准确位置,还需要引入一个栈顶指示变量top。设数组data[MAXSIZE]为栈的存储空间,其中MAX-SIZE是一个预先设定的常数,为允许进栈结点的最大可能数目。
初始时栈空,top等于0。当top不等于0时,data[0]为栈底元素,即为当前停留在栈中时间最长的元素。而data[top-1]为最后入栈的元素。当top==MAXSIZE时,表示栈满,如果此时再有结点进栈,将发生“上溢”的错误,而当top==0时再执行出栈操作,将发生“下溢”的错误。
‘捌’ 数据结构,链式栈问题,求解决。
/*===========================================
链栈基本操作
===========================================*/
#include<stdio.h>
#include<malloc.h>
#defineOK0
#defineERROR1
#defineSIZE20
/*===========================================
数据结构
===========================================*/
typedefstructnode
{
intdata;
structnode*next;
}NODE;
/*===========================================
创建链栈的第一个节点
===========================================*/
NODE*CreateStack(NODE*s,inte)
{
s=(NODE*)malloc(sizeof(NODE));
s->data=e;
s->next=NULL;
returns;
}
/*===========================================
进栈函数
===========================================*/
intPushStack(NODE*s,int*figure,inte)
{
if((*figure)>SIZE)
{
printf("栈满,无法进栈! ");
returnERROR;
}
NODE*node,*p;
p=s;
node=(NODE*)malloc(sizeof(NODE));
node->data=e;
while(p->next!=NULL)
p=p->next;
p->next=node;//经过测试,问题就在此行
printf("测试figure:%d",*figure);
node->next=NULL;
(*figure)++;
returnOK;
}
/*===========================================
出栈函数
===========================================*/
intPopStack(NODE*s,int*figure)
{
intpopdata;
NODE*p,*q;
p=s;
if((*figure)==0)
{
printf("当前栈中无元素,操作失败!");
returnERROR;
}
while(p->next->next!=NULL)
p=p->next;
q=p->next;
popdata=q->data;
free(q);
q=NULL;
p->next=NULL;
(*figure)--;
returnpopdata;
}
/*===========================================
显示栈中元素
===========================================*/
voidDisplayStack(NODE*s,int*figure)
{
switch(*figure)
{
case0:
printf("当前栈中无元素!");break;
case1:
printf("当前栈中共有1个元素,是:%d",s->data);
printf(" ");
break;
default:
NODE*p=s;//一样要给p赋值
printf("当前栈中共有%d个元素,分别是:",*figure);
do
{
printf("%d ",p->data);
p=p->next;
}
while(p!=NULL);
printf(" ");
break;
}
}
/*===========================================
销毁链栈
===========================================*/
voidDestroyStack(NODE*s,int*figure)
{
NODE*p,*q;
p=q=s;
while(p->next!=NULL)
{
p=p->next;
free(q);
q=p;
}
free(p);
*figure=0;
}
/*===========================================
main函数
===========================================*/
intmain()
{
NODE*s=NULL,*h;
intcount=0;
int*figure;//指针figure为计数器,记录链栈中元素个数
figure=&count;
intoption;
intdata;
printf("创建栈,输入栈底元素:");
scanf("%d",&data);
h=CreateStack(s,data);
s=h;//这里要给s赋值
(*figure)++;
printf("链栈以创建完毕! ");
do
{
printf("请选择下列操作:1.元素进栈 2.元素出栈 3.显示栈中元素 4.销毁链栈 输入“0”退出程序 ");
printf("选择操作:");
scanf("%d",&option);
printf(" ");
switch(option)
{
case0:
printf("操作结束,按任意键退出! ");break;
case1:
intpushdata;
printf("输入进栈元素:");
scanf("%d",&pushdata);
PushStack(s,figure,pushdata);break;
case2:
intpopdata;
popdata=PopStack(h,figure);
printf("当前出栈元素是:%d",popdata);break;
case3:
DisplayStack(h,figure);break;
case4:
DestroyStack(s,figure);break;
default:
printf("无此操作! ");break;
}
}while(option!=0);
return0;
}
‘玖’ 分别就栈的顺序存储结构和链式存储结构实现栈的各种基本操作。
顺序存储结构
#include<iostream>
typedef char ElemType;
#define MaxSize 100
using namespace std;
typedef struct
{
ElemType data[MaxSize];
int top;
}sqStack;
void InitStack(sqStack *&s);//初始化栈
void ClearStack(sqStack *&s);//摧毁栈
int StackLength(sqStack *s);//返回栈的长度
bool StackEmpty(sqStack *s);//判断栈是否为空
int Push(sqStack *&s,ElemType e);//进栈
int Pop(sqStack *&s,ElemType &e);//出栈
int GetTop(sqStack *s,ElemType &e);//取栈顶元素
void DispStack(sqStack *s);//显示栈中元素值
int main()
{
return 0;
}
void InitStack(sqStack *&s)//初始化栈
{
s=new sqStack;
s->top=-1;
}
void ClearStack(sqStack *&s)//摧毁栈
{
delete s;
}
int StackLength(sqStack *s)//返回栈的长度
{
return (s->top+1);
}
bool StackEmpty(sqStack *s)//判断栈是否为空
{
return (s->top==-1);
}
int Push(sqStack *&s,ElemType e)//进栈
{
if(s->top==MaxSize-1)
return 0;
s->top++;
s->data[s->top]=e;
return 1;
}
int Pop(sqStack *&s,ElemType &e)//出栈
{
if(s->top==-1)
return 0;
e=s->data[s->top];
s->top--;
return 1;
}
int GetTop(sqStack *s,ElemType &e)//取栈顶元素
{
if(s->top==-1)
return 0;
e=s->data[s->top];
return 1;
}
void DispStack(sqStack *s)//显示栈中元素值
{
for(int i=s->top;i>=0;i--)
cout<<s->data[i]<<" ";
cout<<endl;
}
链式存储结构
typedef char ElemType;
typedef struct linknode
{
ElemType data;
struct linknode *next;
}LiStack;
void InitStack(LiStack *&s);//初始化栈
void ClearStack(LiStack *&s);//摧毁栈
int StackLength(LiStack *s);//返回栈的长度
bool StackEmpty(LiStack *s);//判断栈是否为空
void Push(LiStack *&s,ElemType e);//进栈
int Pop(LiStack *&s,ElemType &e);//出栈
int GetTop(LiStack *s,ElemType &e);//取栈顶元素
void DispStack(LiStack *s);//显示栈中元素值
int main()
{
return 0;
}
void InitStack(LiStack *&s)//初始化栈
{
s=new LiStack;
s->next=NULL;
}
void ClearStack(LiStack *&s)//摧毁栈
{
for(LiStack *p=s->next;p;p=p->next)
{
delete s;
s=p;
p=p->next;
}
delete s;
}
int StackLength(LiStack *s)//返回栈的长度
{
int i=0;
for(LiStack *p=s->next;p;p=p->next)
i++;
return i;
}
bool StackEmpty(LiStack *s)//判断栈是否为空
{
return (s->next==NULL);
}
void Push(LiStack *&s,ElemType e)//进栈
{
LiStack *p=new LiStack;
p->data=e;
p->next=s->next;
s->next=p;
}
int Pop(LiStack *&s,ElemType &e)//出栈
{
LiStack *p;
if(s->next==NULL)
return 0;
p=s->next;
e=p->data;
s->next=p->next;
delete p;
return 1;
}
int GetTop(LiStack *s,ElemType &e)//取栈顶元素
{
if(s->next==NULL)
return 0;
e=s->next->data;
return 1;
}
void DispStack(LiStack *s)//显示栈中元素值
{
LiStack *p=s->next;
for(;p;p=p->next)
cout<<p->data<<" ";
cout<<endl;
}
‘拾’ 带链栈的栈底指针是随栈的操作而动态变化的 这句话为什么是对的
以上说法不够严谨。
链式存储的栈结构,栈底指针的动态变化是有严格约束条件的,即:出栈操作中栈内仅有一个元素时或者入栈操作中栈内没有元素时,栈底指针才会变化。随着栈操作而动态变化应该用于描述栈顶指针。
栈顶指针不变应该,但是我觉得是栈顶指针随着栈顶元素变化而变化,栈顶指针是表示栈顶元素的位置,占地元素不同位置,栈顶指针就不同,如同一位置不同元素的指针也是相同的,因为指针是地址,只是取这个地址的值会不同。
(10)链式栈的栈底元素缓存数据吗扩展阅读:
计算机中的堆栈主要用来保存临时数据,局部变量和中断/调用子程序程序的返回地址。
堆栈指针是在栈操作过程中,有一个专门的栈指针(习惯上称它为TOP),指出栈顶元素所在的位置。
堆栈指针总是指向栈顶元素。
堆栈可以使向下生长的(向低地址),也可以是向上生长的。
如果堆栈是向上生长的,数据入栈的时候,堆栈指针先加1,再压栈。出栈的时候先弹出数据,堆栈指针再减1。如果堆栈是向下生长的,数据入栈时指针将减1,数据出栈时指针将加1。