(九)栈(链式存储)-- 拉个链链,盘他!

栈(链式存储)

栈的链式存储书上没有,没有!但是不能影响我们前进的脚步。盘他!
栈的链式存储实际上就是单链表,仅仅在尾部操作,这就是重点。

1.结构
链式存储,当然要典型的链表的结构

typedef int SElemType;

typedef struct SingleList
{
	SElemType data;
	struct SingleList* next;
} SList;

然后再添加一个栈的结构,这个全局结构记录了栈的关键信息。

typedef struct
{
	SList* top;
	SList* base;
	int stack_size;
} SQS;

2.重点

  • 先创建一个头节点,这个节点就是栈底。在顺序存储中栈底占用了一个地址,也就是一个字节,链式存储中先开辟了一个节点,这个节点就是栈底,多大?sizeof(Slist),应该是8个字节。
  • 压入栈一个元素,临时开辟一个节点的内存,不像顺序存储的时候先开辟一段连续的空间。
  • 理论上没有栈满的情况,这个取决于内存的大小。顺序存储是一点一点开辟固定大小空间,栈满经常发生,就要扩容。链式存储因为是动态开辟空间,所以基本不会发生栈满的情况。
  • 由于是链式存储,不能使用 top++、top–这种操作!!!!
  • 要注意链式存储的形态,有图有真相。
    在这里插入图片描述
    可以看到节点的地址不连续,出栈的时候也是一样。结合下边的代码看吧。

3.代码
sqstacklist.h

#pragma once
#include <stdio.h>
#include <stdlib.h>

typedef int SElemType;

typedef struct SingleList
{
	SElemType data;
	struct SingleList* next;
} SList;

typedef struct
{
	SList* top;
	SList* base;
	int stack_size;
} SQS;

typedef int Status;
#define ERROR 0;
#define OK    1;

//初始化链表,建立一个空头
Status Init_stack(SQS* s);

//压栈
Status Push(SQS* s, SElemType e);

//出栈
Status Pop(SQS* s, SElemType* e);

//打印链表
void PrintSingleList(SList* sl);

sqstacklist.c

#pragma once
#include"sqstacklist.h"

extern SQS ssq;

Status Init_stack(SQS* s)
{
	SList* lnew;
	lnew = (SList*)malloc(sizeof(SList));
	if (!lnew)
	{
		printf("内存分配失败。");
		return ERROR;
	}
	lnew->next = NULL;
	s->base = lnew;
	s->top = lnew;
	s->stack_size = 0;
	return OK;
}

Status Push(SQS* s, SElemType e)
{
	SList* lnew;

	lnew = (SList*)malloc(sizeof(SList));
	if (!lnew)
	{
		printf("内存分配失败。");
		return ERROR;
	}
	lnew->data = e;
	lnew->next = NULL;
	s->top->next = lnew;
	s->top = lnew;
	s->stack_size++;
	return OK;
}

//出栈
Status Pop(SQS* s, SElemType* e)
{
	SList* ll;
	int i;
	if (s->stack_size <= 0)
	{
		printf("栈空额。弹。。弹。。。弹个毛线。\n");
		return ERROR;
	}
	ll = s->base;
	for (i = 0; i < s->stack_size - 1; i++)
	{
		ll = ll->next;
	}
	*e = s->top->data;
	free(s->top);
	s->top = ll;
	s->top->next = NULL;
	s->stack_size--;
	return OK;
}

void PrintSingleList(SList* sl)
{
	int i = 0;
	//带有头节点,跳过头结点
	sl = sl->next;
	while (sl)
	{
		printf("\t%d:\t%d\n", i++, sl->data);
		sl = sl->next;
	}
}

测试代码

#include <stdio.h>
#include<stdlib.h>
#include"sqstacklist.h"


SQS ssq;

int main()
{
	int i,n,j;
	printf("初始化----\n");
	Init_stack(&ssq);
	printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d.\n",ssq.base,ssq.top,ssq.stack_size);
	printf("压栈----\n");
	Push(&ssq, 1);
	printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d,\tdata=%d\n", ssq.base, ssq.top, ssq.stack_size,ssq.top->data);
	Push(&ssq, 2);
	printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d,\tdata=%d\n", ssq.base, ssq.top, ssq.stack_size, ssq.top->data);
	Push(&ssq, 3);
	printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d,\tdata=%d\n", ssq.base, ssq.top, ssq.stack_size, ssq.top->data);
	Push(&ssq, 4);
	printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d,\tdata=%d\n", ssq.base, ssq.top, ssq.stack_size, ssq.top->data);
	Push(&ssq, 5);
	printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d,\tdata=%d\n", ssq.base, ssq.top, ssq.stack_size, ssq.top->data);

	//PrintSingleList(ssq.base);
	printf("弹栈----\n");
	j = ssq.stack_size;
	for (i = 0; i < j; i++)
	{
		Pop(&ssq, &n);
		printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d,\tdata=%d\n", ssq.base, ssq.top, ssq.stack_size, n);
	}
	Pop(&ssq, &n);

	system("pause");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值