IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 栈的实现(c语言)--- 数据结构 -> 正文阅读

[数据结构与算法]栈的实现(c语言)--- 数据结构

1. 栈的简介

1.1栈的特点

栈(Stack)是一种线性存储结构,它最大的特点就是:栈中的数据遵循先进后出的原则,想要在栈中插入和删除数据,只能在栈顶操作

1.2栈的相关概念

栈的相关概念:
1.栈顶与栈底:允许元素插入与删除的一端称为栈顶,另一端称为栈底。
2.入栈:栈的插入操作,叫做进栈,也称压栈。
3.出栈:栈的删除操作,也叫做弹栈。
下面我将介绍栈的两种实现结构,一种是栈的顺序存储,一种是栈的链式存储

2.栈的顺序存储

一般对于栈的操作主要有以下几个部分:
1.初始化栈,也就是创建出一个栈的结构
2.入栈操作
3.出栈操作
4.获取栈顶元素
5.获取栈的大小
6.判断栈是否为空
7.销毁栈

首先我们要创建一个栈的结构,结构体中包含数据块,以及定义一个变量来来记录栈的大小。

#define MAX 1024
typedef struct SStack
{
	void* date[MAX];//将数据类型定义成为void* 这样就可以接收任意类型的数据了
	int size;
};

2.1初始化栈

SStack* initStack()
{
	SStack* stack = (SStack*)malloc(sizeof(SStack));
	if(stack==NULL)
	{
	   return NULL;
	}
	memset(date,0,sizeof(void*)*MAx);//将数据全部置为0
	stack->size = 0;
	return stack;
}

2.1入栈

void pushStack(SStack* stack,void* date)
{
	if(stack==NULL||date==NULL)
	{
		return;
	}
	if(stack->size==MAX)//判断栈是否放满
	{
		return;
	}
	stack->date[stack->size] = date; //将数据放到栈顶
	stack->szie++;
}

2.3出栈

void popStack(SStack* stack)
{
	if(stack==NULL)
	{
		return;
	}
	if(stack->size==0)
	{
		return;
	}
	//将最后一个元素置空,执行出栈
	stack->date[stack->size-1]=NULL;
	stack->size--;
}

2.4 获取栈顶元素

void* getTopStack(SStack* stack)
{
	if(stack==NULL)
	{
		return NULL;
	}
	if(stack->size==0)
	{
		return NULL;
	}
	//返回栈顶元素
	return stack->date[stack->size-1];
}

2.5获取栈的大小

int sizeOfStack(SStack* stack)
{
	if(stack==NULL)
	{
		return -1;
	}
	return stack->szie;
}

2.6 判断栈是否为空

bool isEmptyStack(SStack* stack)
{
	if(stack==NULL)
	{
		return true;
	}	
	if(stack->size==0)
	{
		return true;
	}
	return false;//不为空返回false
}

2.7栈的销毁

void destoryStack(SStack* stack)
{
	if(stack==NULL)
	{
	   return ;
	}
	free(stack);
	stack = NULL;
}

2.8 测试部分

#include "stack.h"
//定义一个Person的结果体类型
struct Person
{
	char name[20];
	int age;

};


void test()
{
	//初始化栈
	SStack* stack = initStack();
	struct Person p1 = { "陈",10 };
	struct Person p2 = { "卢",12 };
	struct Person p3 = { "张",14 };
	struct Person p4 = { "王",15 };
	struct Person p5 = { "周",11 };
	struct Person p6 = { "李",16 };
	//将数据进行入栈操作
	pushStack(stack, &p1);
	pushStack(stack, &p2);
	pushStack(stack, &p3);
	pushStack(stack, &p4);
	pushStack(stack, &p5);
	pushStack(stack, &p6);

	int size = sizeOfStack(stack);
	//打印出出栈前栈中元素的个数
	printf("栈的大小为:%d\n", size);

	while (!isEmptyStack(stack)) //如果栈不为空 进行访问栈顶元素 并且出栈
	{
		struct Person* pTop = getTopStack(stack); //得到栈顶元素
		//打印栈顶元素的信息
		printf("栈顶元素的姓名:%s  年龄:%d\n", pTop->name, pTop->age);
		//进行出栈操作
		popStack(stack); 
	}
	 size = sizeOfStack(stack);
	printf("栈的大小为:%d\n", size);//打印出出栈后栈中元素的个数

	destoryStack(stack);
}

int main()
{
	test();
	return 0;
}

下面是程序运行的结果:可以清楚看到入栈的顺序与出栈的顺序,完全相反。
在这里插入图片描述

3.栈的链式存储

3.1链式存储的简单介绍

关于链式存储,显而易见,这就跟链表有关,而我们都知道对于链表而言,我们为了方便链表的操作,都会定义一个头结点出来,所以对于栈来说,我们也要定义一个头结点。那么问题来了,我们知道栈的结构分为栈顶和栈底,那么我们这个头结点是指向栈顶呢,还是指向栈底呢?
我们前面讲了,栈这种数据结构有一个特点:就是入栈和出栈都是对栈顶来进行操作的,如果我们把头结点指向栈底,那么对于栈顶的元素的插入,和删除操作就不太方便,所以综上所述,我们应该把头结点指向栈顶。

3.2链式存储中入栈和出栈的简单示意图

下面为链式存储中栈的数据的结构
在这里插入图片描述
当有新数据进来时,我们就进行头,怎么头插呢,具体的我们来看图:
在这里插入图片描述
我们让newnode->next指向栈中第一个数据(也就是top),然后用
phead->next,执象我们的新节点,这就完成了。

3.3代码实现过程

栈的链式存储的主要功能和顺序存储的主要能类似,只是多了一个结构体指针。下面我就不分开写了


typedef struct StackNode
{
	struct StackNode* next; //只维护指针域

}StackNode;
//定义栈的结构体
typedef struct LinkStack
{
	StackNode phead; //头节点
	int size;//记录栈的大小
}LinkStack;


//初始化
LinkStack* initLinkStack()
{
	LinkStack* stack = malloc(sizeof(LinkStack));
	if (stack == NULL)
	{
		return NULL;
	}
	stack->phead.next = NULL;
	stack->size = 0;
	return stack;
}

//入栈
void pushLinkStack(LinkStack* stack, void* date)
{
	if (stack == NULL || date == NULL)
	{
		return;
	}
	
	//拿到用户数据的前四个字节,进行头插,
	StackNode* myNode = date;
	//入栈
	myNode->next = stack->phead.next;
	stack->phead.next = myNode;

	stack->size++;
}


//出栈
void popLinkStack(LinkStack* stack)
{
	if (stack == NULL)
	{
		return;
	}
	if (stack->size <= 0)
	{
		return;
	}
	StackNode* first = stack->phead.next; //得到第一个有数据的节点
	//进行出栈操作
	stack->phead.next = first->next;
	//更新链表长度
	stack->size--;
}

//获取栈顶元素
void* getTopLinkStack(LinkStack* stack)
{
	if (stack == NULL)
	{
		return NULL;
	}
	if (stack->size == 0)
	{
		return NULL;
	}

	return stack->phead.next;
}


//获取栈的大小
int sizeOfLinkStack(LinkStack* stack)
{
	if (stack == NULL)
	{
		return -1;
	}

	return stack->size;
}

//判断栈是否为空
bool isEmptyLinkStack(LinkStack* stack)
{
	if (stack == NULL)
	{
		return true;
	}
	if (stack->size == 0)
	{
		return true;
	}
	return false; //不为空返回false
}

//销毁栈
void destoryLinkStack(LinkStack* stack)
{
	if (stack == NULL)
	{
		return;
	}
	free(stack);
	stack = NULL;
}

下面是测试部分代码,跟顺序储存大同小异。

struct Person
{
	StackNode node; //预留四个字节,也可以写成int* void*,只要是四个字节的空间就行
	char name[20];
	int age;
};

void test()
{
	struct Person p1 = { "NULL", "陈", 10 };
	struct Person p2 = { "NULL", "卢", 12 };
	struct Person p3 = { "NULL", "张", 14 };
	struct Person p4 = { "NULL", "王", 15 };
	struct Person p5 = { "NULL", "周", 11 };
	struct Person p6 = { "NULL", "李", 16 };
	LinkStack* stack = initLinkStack();

	pushLinkStack(stack, &p1);
	pushLinkStack(stack, &p2);
	pushLinkStack(stack, &p3);
	pushLinkStack(stack, &p4);
	pushLinkStack(stack, &p5);
	pushLinkStack(stack, &p6);

	int size = sizeOfLinkStack(stack);
	printf("栈空间的大小:%d\n", size);

	while (!isEmptyLinkStack(stack))
	{
		struct Person* pTop = getTopLinkStack(stack);
		printf("姓名:%s, 年龄:%d\n", pTop->name, pTop->age);
		popLinkStack(stack);
	}
	 size = sizeOfLinkStack(stack);
	printf("栈空间的大小:%d\n", size);
	destoryLinkStack(stack);
}

int main()
{
	test();
	return 0;
}

下面是代码运行结果:
在这里插入图片描述

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-10-06 12:28:58  更:2021-10-06 12:31:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 11:50:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码