栈的链式存储结构

时间:2022-02-22 00:15:33

栈的链式存储简称链栈。

在链栈中将链表的头指针和栈顶指针合二为一。

 栈的链式存储结构

对于链栈来说基本不存在栈满的情况,除非内存以及没有可用空间。对于空栈来说链表原定义是头指针指向空,那么链栈的空其实就是top==NULL的时候。

一、结构

typedef int SElemType;//此处可能是个结构体,练习使用int型足够了

 

typedef struct stacknode
{
         SElemTypedata;
         structstacknode * next;
}StackNode,* LinkStack;

二、栈的链式存储进栈操作

进栈操作,假设元素值为e新结点是s,top为栈顶指针则进栈操作如下:

栈的链式存储结构

算法思路:

1.      分配一个节点s;

2.      将结点值赋值给s->data;

3.      把当前栈顶元素赋值给新结点的直接后继;

4.      将新结点p赋值给栈顶。

三、栈的链式存储出栈操作

栈的链式存储结构

出栈操作,假设变量p用来存储要删除的栈顶结点,将栈顶指针下移一位,最后释放p即可。

算法思路:

1.      检查是否是空栈,空栈则返回;

2.      获取栈顶元素,将栈顶赋值给p;

3.      使得栈顶指针下移一位;

4.      释放p

四、时间复杂度

没有任何循环,时间复杂度都是O(1)。

对比一下顺序栈与链栈的时间复杂度均为O(1);空间复杂度上顺序栈需要提前分配一个固定的长度,可能会造成空间的浪费,但是它的优势是存取时候方便,并且链栈要求每个元素都有指针域,这同时也增加了一些内存开销,但是对于栈的长度无限制。所以链栈和顺序栈的区别和线性表中的讨论是一样的:如果栈的使用过程中元素变化不可预料,有时候很小,有时候非常大,那么最好使用链栈,反之,如果它的变化在可控范围内,建议使用顺序栈会更好一些。

五、代码示例

#include <stdio.h>
#include <string.h>
#include <malloc.h>

#define ERROR -1
#define OK 0
typedef int SElemType;//此处可能是个结构体,练习使用int型足够了

typedef struct stacknode
{
	SElemType data;
	struct stacknode * next;
}StackNode,* LinkStack;

//判栈空
int StackEmpty(LinkStack top)
{
	if(top->next==NULL)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
//入栈函数
LinkStack Push(LinkStack top,SElemType e)
{
    StackNode * p = (StackNode *)malloc(sizeof(StackNode));
    if(p != NULL)
    {
        p->data=e;
        p->next=top->next;//把当前栈顶元素赋值给新结点的直接后继
        top->next=p;//将新结点p赋值给栈顶
    }
    else
    {
        printf("分配结点失败\n");
    }
    return top;

}

//出栈函数
int Pop(LinkStack top)
{
	StackNode * p;
	SElemType t;
	if(StackEmpty(top))
	{
		printf("空栈\n");
	}
	else
	{
		p = top->next;//将栈顶赋值给p
		t = p->data;
		top->next = p->next;//使得栈顶指针下移一位
		free(p);
	}
	return t;
}
//打印函数
void PrintStack(LinkStack top)
{
    if(top->next==NULL)
    {
		printf("空栈\n");
    }
    else
    {
        while(top->next!=NULL)
        {
			printf("元素:%d\n",top->next->data);
            top=top->next;
        }
    }
}
//取栈顶元素
int StackTop(LinkStack top)
{
	if(StackEmpty(top))
	{
		printf("空栈\n");
	}
	return top->next->data;
}

//栈的长度
int StackLen(LinkStack top)
{
    int len=0;
	while(top->next!=NULL)
	{
		len++;
		top=top->next;
	}
    return len;
}
//销毁栈
void DestroyStack(LinkStack top)
{
	LinkStack q;
	while(top)
	{
		q=top->next;
		free(top);
		top=q;
	}
	printf("销毁成功");

}
//栈初始化
void InitStack(LinkStack top)
{
    top->next=NULL;
}


int main()
{
	int i = 0;
    LinkStack top;
    top = (LinkStack)malloc(sizeof(StackNode));    //注意
	printf("\n=======初始化操作=========\n");
	InitStack(top);

    printf("\n=======入栈操作=========\n");
    for(i = 0;i<10;i++)
    {
        Push(top,i);    //入栈
    }
	printf("栈大小:%d\n",StackLen(top));
	printf("\n=======打印栈信息=========\n");
    PrintStack(top);    //打印栈

	printf("\n=======出栈操作=========\n");
    if(top->next!=NULL)//出栈
    {
	printf("出栈元素::%d\n",Pop(top));
	}
	else
	{
		printf("空栈\n");
	}
	printf("\n=======取栈顶元素=========\n");
	if(StackEmpty(top)==1)//取栈顶元素
    {
		printf("空栈\n");
	}
	else
    {
	printf("栈顶元素:%d\n",StackTop(top));
	}
	printf("\n=======判断栈是否为空=========\n");
	if(StackEmpty(top)==1)//判断栈是否为空
    {
		printf("空栈\n");
	}
	else
    {
		printf("不是空栈\n");
	}

	printf("\n=======返回栈的元素个数=========\n");
	if(StackEmpty(top)==1)//返回栈的元素个数
    {
		printf("空栈\n");
	}
	else
	{
		printf("栈大小:%d\n",StackLen(top));
	}
	printf("\n=======销毁栈=========\n");
	DestroyStack(top);
    return 0;
}