数据结构--(栈)总结

目录

1.顺序栈

(1)数据结构

(2)函数列表

1.初始化栈

2.判空

3.出栈

4.入栈

5.返回栈中元素个数

6.返回栈顶元素

7.清空栈

8.销毁栈

9.打印栈

(3)完整代码

(4)运行结果

2.链式栈

(1)数据结构

(2)函数列表

1.初始化栈

2.判空

3.入栈

4.出栈

5.返回栈中元素个数

6.返回栈顶元素

7.清空栈

8.销毁栈

9.打印栈

(3)完整代码

(4)运行结果


1.顺序栈

说明:本篇代码中,顺序栈栈顶指针初始值为 -1,代码中,数组采用的是 int 类型的指针,指向一块通过malloc 开辟的内存空间。也可以通过 Elemtype data[MAXSIZE] 指定。

(1)数据结构
#define MAXSIZE 100
typedef int Elemtype;
typedef struct SqStack
{
	//Elemtype data[MAXSIZE];
	Elemtype* data;	//指向一块内存
	int top;	//栈顶指针
}SqStack;
(2)函数列表
        1.初始化栈
//初始化栈
SqStack* Init_Stack()
{
	/*1.为结构体分配内存*/
	SqStack* Sq = (SqStack*)malloc(sizeof(SqStack));

	/*2.初始化数据指针*/
	Sq->data = (Elemtype*)malloc(sizeof(Elemtype) * MAXSIZE);

	/*3.初始化栈顶指针*/
	Sq->top = -1;

	return Sq;
}
        2.判空

注:判空时需要先判断头节点是否存在,即:判断头节点是否为空,再判断是否有元素。顺序不能反转。因为当头节点未定义时,使用 Sq->top 会造成空指针的引用,引发段错误。

//判断一个栈是否为空
bool Stack_Is_Empty(SqStack* Sq)
{
	/*1.判断头节点是否为空*/
	if (Sq == NULL)
	{
		printf("栈未定义!\n");
		return true;
	}

	/*2.判断是否有元素*/
	if (Sq->top == -1)
	{
		return true;
	}
	return false;
}
        3.出栈
//出栈
bool Pop(SqStack* Sq, Elemtype* d)
{
	/*1.判空*/
	if (Stack_Is_Empty(Sq))
	{
		printf("栈为空\n");
		return false;
	}

	/*2.出栈*/
	*d = Sq->data[Sq->top--];  // 修正这里的顺序
	return true;
}
        4.入栈

注:元素入栈前,需要先判空,再判断栈是否已经满了,不能颠倒顺序,栈空时可能造成使用空指针的情况。

//入栈
bool Push(SqStack* Sq, Elemtype d)
{
	/*1.判空*/
	if (Sq == NULL)
	{
		printf("栈为空\n");
		return false;
	}

	/*2.判满*/
	if (Sq->top == MAXSIZE - 1)
	{
		printf("栈满,无法入栈!\n");
		return false;
	}

	/*3.入栈*/
	Sq->top += 1;
	Sq->data[Sq->top] = d;  // 修正这里的顺序

	return true;
}
        5.返回栈中元素个数

注:数组下标从 0 开始,栈底默认为 -1 所以元素的个数需要在 top 的基础上 +1

//返回栈的元素个数
int Get_Stack_Length(SqStack* Sq)
{
	/*1.判空*/
	if (Stack_Is_Empty(Sq))
	{
		printf("栈为空\n");
		return 0;
	}
	return Sq->top + 1;
}
        6.返回栈顶元素
//返回栈顶元素
bool Get_Top(SqStack* Sq, Elemtype* d)
{
	/*1.判空*/
	if (Stack_Is_Empty(Sq))
	{
		printf("栈为空\n");
		return false;
	}

	*d =  Sq->data[Sq->top];
	return true;
}
        7.清空栈

注:直接重置 top -1 即可,top 作为栈顶指针,元素读取超过 top 都是 "越界" 的情况,不考虑。新的数据会覆盖老的数据,不会造成影响。

//清空一个栈
void Clear_Stack(SqStack* Sq)
{
	/*1.判空*/
	if (Stack_Is_Empty(Sq))
	{
		printf("栈为空\n");
		return;
	}

	/*2.重置 data 数组*/
	Sq->top = -1;
}
        8.销毁栈

注:data 数组也是通过 malloc 在堆区创建的,需要手动释放,并且先与 Sq 头指针释放,否则先释放了 Sq 头指针,再去释放 data 所指向的内存可能会造成未知结果。因为 Sq 已经被释放,Sq 不一定还存有 data 的地址,或 Sq 已经被置空,造成空指针引用,引发段错误。

//销毁栈
SqStack* Destory_Stack(SqStack* Sq)
{
	/*1.判空*/
	if (Sq == NULL)
		return NULL;

	/*2.释放结点*/
	free(Sq->data);
	Sq->data = NULL;
	free(Sq);
	Sq = NULL;
	return Sq;
}
        9.打印栈

注:栈是先进后出的线性结构,这里通过 for 循环遍历,只是为了验证代码是否准确。

//打印栈
void Print_SqStack(SqStack* Sq)
{
	printf("\n打印栈:\n");
	printf("------------------------\n");
	if (Stack_Is_Empty(Sq))
	{
		printf("栈空!");
	}
	else
	{
		for (int i = 0; i <= Sq->top; i++)
		{
			printf("%d ", Sq->data[i]);
		}
	}
	printf("\n------------------------\n");
}
(3)完整代码
#include<stdio.h>
#include<stdbool.h>

#define MAXSIZE 100
typedef int Elemtype;
typedef struct SqStack
{
	//Elemtype data[MAXSIZE];
	Elemtype* data;	//指向一块内存
	int top;	//栈顶指针
}SqStack;

//初始化栈
SqStack* Init_Stack()
{
	/*1.为结构体分配内存*/
	SqStack* Sq = (SqStack*)malloc(sizeof(SqStack));

	/*2.初始化数据指针*/
	Sq->data = (Elemtype*)malloc(sizeof(Elemtype) * MAXSIZE);

	/*3.初始化栈顶指针*/
	Sq->top = -1;

	return Sq;
}

//判断一个栈是否为空
bool Stack_Is_Empty(SqStack* Sq)
{
	/*1.判断头节点是否为空*/
	if (Sq == NULL)
	{
		printf("栈未定义!\n");
		return true;
	}

	/*2.判断是否有元素*/
	if (Sq->top == -1)
	{
		return true;
	}
	return false;
}

//出栈
bool Pop(SqStack* Sq, Elemtype* d)
{
	/*1.判空*/
	if (Stack_Is_Empty(Sq))
	{
		printf("栈为空\n");
		return false;
	}

	/*2.出栈*/
	*d = Sq->data[Sq->top--];  // 修正这里的顺序
	return true;
}

//入栈
bool Push(SqStack* Sq, Elemtype d)
{
	/*1.判空*/
	if (Sq == NULL)
	{
		printf("栈为空\n");
		return false;
	}

	/*2.判满*/
	if (Sq->top == MAXSIZE - 1)
	{
		printf("栈满,无法入栈!\n");
		return false;
	}

	/*3.入栈*/
	Sq->top += 1;
	Sq->data[Sq->top] = d;  // 修正这里的顺序

	return true;
}

//返回栈的元素个数
int Get_Stack_Length(SqStack* Sq)
{
	/*1.判空*/
	if (Stack_Is_Empty(Sq))
	{
		printf("栈为空\n");
		return 0;
	}
	return Sq->top + 1;
}

//返回栈顶元素
bool Get_Top(SqStack* Sq, Elemtype* d)
{
	/*1.判空*/
	if (Stack_Is_Empty(Sq))
	{
		printf("栈为空\n");
		return false;
	}

	*d =  Sq->data[Sq->top];
	return true;
}

//清空一个栈
void Clear_Stack(SqStack* Sq)
{
	/*1.判空*/
	if (Stack_Is_Empty(Sq))
	{
		printf("栈为空\n");
		return;
	}

	/*2.重置 data 数组*/
	Sq->top = -1;
}

//销毁栈
SqStack* Destory_Stack(SqStack* Sq)
{
	/*1.判空*/
	if (Sq == NULL)
		return NULL;

	/*2.释放结点*/
	free(Sq->data);
	Sq->data = NULL;
	free(Sq);
	Sq = NULL;
	return Sq;
}


//打印栈
void Print_SqStack(SqStack* Sq)
{
	printf("\n打印栈:\n");
	printf("------------------------\n");
	if (Stack_Is_Empty(Sq))
	{
		printf("栈空!");
	}
	else
	{
		for (int i = 0; i <= Sq->top; i++)
		{
			printf("%d ", Sq->data[i]);
		}
	}
	printf("\n------------------------\n");
}

int main()
{
	//创建栈
	SqStack* Sq = Init_Stack();

	//判空
	Stack_Is_Empty(Sq);
	
	//入栈测试
	printf("1 2 3 4 5入栈\n");
	Push(Sq, 1);
	Push(Sq, 2);
	Push(Sq, 3);
	Push(Sq, 4);
	Push(Sq, 5);

	//输出元素个数
	printf("栈中有 %d 个元素\n", Get_Stack_Length(Sq));
	Print_SqStack(Sq);

	//获取栈顶元素
	Elemtype data;
	Get_Top(Sq, &data);
	printf("栈顶元素为:%d", data);

	//出栈
	printf("\n\n出栈两个元素\n");
	Pop(Sq, &data);
	printf("出栈:%d\n", data);
	Pop(Sq, &data);
	printf("出栈:%d\n", data);
	Print_SqStack(Sq);

	//获取栈顶元素
	Get_Top(Sq, &data);
	printf("栈顶元素为:%d\n", data);

	//清空栈
	printf("\n清空栈");
	Clear_Stack(Sq);
	//判空
	Stack_Is_Empty(Sq);
	Print_SqStack(Sq);

	//销毁栈
	printf("\n销毁栈");
	Sq = Destory_Stack(Sq);
	Print_SqStack(Sq);
	return 0;
}
(4)运行结果


2.链式栈

(1)数据结构

注:代码使用的是带头节点的双向链表模型作为栈。链表的头结点作为栈底

typedef int Elemtype;
typedef struct Node
{
	Elemtype data;
	struct Node* next;
	struct Node* prev;
}Node;

//头节点做栈顶
typedef struct LinkStack
{
	Node* top;	//指向栈顶
	Node* bottom;	//指向栈底
	int length;	//元素数量
}LinkStack;
(2)函数列表
        1.初始化栈
//初始化一个栈
LinkStack* Init_Stack()
{
	/*1.初始化头节点*/
	LinkStack* Link = (LinkStack*)malloc(sizeof(LinkStack));
	Link->top = NULL;
	Link->bottom = NULL;
    Link->length = 0;;
	return Link;
}
        2.判空
//判断一个栈是否为空
bool Stack_Is_Empty(LinkStack* LS)
{
	if (LS == NULL || LS->bottom == NULL)
	{
		printf("栈空\n");
		return true;
	}
	return false;
}
        3.入栈
//入栈
bool Push(LinkStack* LS,Elemtype d)
{
	/*1.判空*/
    if (LS == NULL)
    {
        printf("栈空!\n");
        return false;
    }
    
    /*2.创建结点*/
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = d;
    newNode->next = NULL;
    newNode->prev = NULL;


    /*3.插入元素*/
    if (LS->top == NULL)
    {   //链表中没有结点
        LS->top = newNode;
        LS->bottom = newNode;
    }
    else
    {   //首结点做栈顶,头插
        LS->top->prev = newNode;
        newNode->next = LS->top;
        LS->top = newNode;
    }
    LS->length++;
    return true;
}
        4.出栈
//出栈
bool Pop(LinkStack* LS, Elemtype *d)
{
    /*1.判空*/
    if (Stack_Is_Empty(LS))
    {
        printf("栈空\n");
        return false;
    }

    /*2.获取结点的值*/
    *d = LS->top->data;

    /*3.出栈、释放空间*/
    Node* p = LS->top;
    LS->top = p->next;

    /*4.判断链表是否还有结点*/
    if(LS->top != NULL)
        LS->top->prev = NULL;
    else
    {
        LS->top = NULL;
        LS->bottom = NULL;
    }

    free(p);
    p = NULL;
    LS->length--;
    return true;
}
        5.返回栈中元素个数
//返回栈的元素个数
int Get_Stack_Length(LinkStack* LS)
{
    if (Stack_Is_Empty(LS))
    {
        printf("空栈\n");
        return 0;
    }
    return LS->length;
}
        6.返回栈顶元素
//返回栈顶元素
void Get_Stack_Top(LinkStack* LS,Elemtype *d)
{
    if (Stack_Is_Empty(LS))
    {
        printf("空栈\n");
        return;
    }
    *d = LS->top->data;
}
        7.清空栈
//清空一个栈
void Clear_Stack(LinkStack* LS)
{
    /*1.判空*/
    if (Stack_Is_Empty(LS))
        return;

    /*2.逐个释放*/
    Node* p = NULL;
    while (LS->top)
    {
        p = LS->top;
        LS->top = p->next;
        free(p);
        p = NULL;
    }

    /*3.更新头节点*/
    LS->bottom = NULL;
    LS->top = NULL;
    LS->length = 0;
}
        8.销毁栈
//销毁一个栈
LinkStack* Destory_Stack(LinkStack* LS)
{
    Clear_Stack(LS);
    if (LS == NULL)
        return LS;
    free(LS);
    LS = NULL;
    return LS;
}
        9.打印栈
//打印栈
void Print_Stack(LinkStack* LS)
{
    printf("\n打印栈\n");
    printf("-------------------\n");
    if (Stack_Is_Empty(LS))
        printf("空栈!");
    else
    {
        Node* p = LS->top;
        while (p)
        {
            printf("%d ", p->data);
            p = p->next;
        }
        /*逆向打印,验证链式栈是否正确链接*/
        printf("\n");
        p = LS->bottom;
        while (p)
        {
            printf("%d ", p->data);
            p = p->prev;
        }
    }
    printf("\n-------------------\n");
}
(3)完整代码
#include<stdio.h>
#include<stdbool.h>

typedef int Elemtype;
typedef struct Node
{
	Elemtype data;
	struct Node* next;
	struct Node* prev;
}Node;

//头节点做栈顶
typedef struct LinkStack
{
	Node* top;	//指向栈顶
	Node* bottom;	//指向栈底
	int length;	//元素数量
}LinkStack;

//初始化一个栈
LinkStack* Init_Stack()
{
	/*1.初始化头节点*/
	LinkStack* Link = (LinkStack*)malloc(sizeof(LinkStack));
	Link->top = NULL;
	Link->bottom = NULL;
    Link->length = 0;;
	return Link;
}

//判断一个栈是否为空
bool Stack_Is_Empty(LinkStack* LS)
{
	if (LS == NULL || LS->bottom == NULL)
	{
		printf("栈空\n");
		return true;
	}
	return false;
}

//入栈
bool Push(LinkStack* LS,Elemtype d)
{
	/*1.判空*/
    if (LS == NULL)
    {
        printf("栈空!\n");
        return false;
    }
    
    /*2.创建结点*/
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = d;
    newNode->next = NULL;
    newNode->prev = NULL;


    /*3.插入元素*/
    if (LS->top == NULL)
    {   //链表中没有结点
        LS->top = newNode;
        LS->bottom = newNode;
    }
    else
    {   //首结点做栈顶,头插
        LS->top->prev = newNode;
        newNode->next = LS->top;
        LS->top = newNode;
    }
    LS->length++;
    return true;
}

//出栈
bool Pop(LinkStack* LS, Elemtype *d)
{
    /*1.判空*/
    if (Stack_Is_Empty(LS))
    {
        printf("栈空\n");
        return false;
    }

    /*2.获取结点的值*/
    *d = LS->top->data;

    /*3.出栈、释放空间*/
    Node* p = LS->top;
    LS->top = p->next;

    /*4.判断链表是否还有结点*/
    if(LS->top != NULL)
        LS->top->prev = NULL;
    else
    {
        LS->top = NULL;
        LS->bottom = NULL;
    }

    free(p);
    p = NULL;
    LS->length--;
    return true;
}

//返回栈的元素个数
int Get_Stack_Length(LinkStack* LS)
{
    if (Stack_Is_Empty(LS))
    {
        printf("空栈\n");
        return 0;
    }
    return LS->length;
}

//返回栈顶元素
void Get_Stack_Top(LinkStack* LS,Elemtype *d)
{
    if (Stack_Is_Empty(LS))
    {
        printf("空栈\n");
        return;
    }
    *d = LS->top->data;
}

//清空一个栈
void Clear_Stack(LinkStack* LS)
{
    /*1.判空*/
    if (Stack_Is_Empty(LS))
        return;

    /*2.逐个释放*/
    Node* p = NULL;
    while (LS->top)
    {
        p = LS->top;
        LS->top = p->next;
        free(p);
        p = NULL;
    }

    /*3.更新头节点*/
    LS->bottom = NULL;
    LS->top = NULL;
    LS->length = 0;
}

//销毁一个栈
LinkStack* Destory_Stack(LinkStack* LS)
{
    Clear_Stack(LS);
    if (LS == NULL)
        return LS;
    free(LS);
    LS = NULL;
    return LS;
}

//打印栈
void Print_Stack(LinkStack* LS)
{
    printf("\n打印栈\n");
    printf("-------------------\n");
    if (Stack_Is_Empty(LS))
        printf("空栈!");
    else
    {
        Node* p = LS->top;
        while (p)
        {
            printf("%d ", p->data);
            p = p->next;
        }
        /*逆向打印,验证链式栈是否正确链接*/
        printf("\n");
        p = LS->bottom;
        while (p)
        {
            printf("%d ", p->data);
            p = p->prev;
        }
    }
    printf("\n-------------------\n");
}

int main() {
    LinkStack* stack = Init_Stack();

    // 测试 Push
    printf("入栈10,20,30,40,50\n");
    for (int i = 1; i <= 5; i++) {
        Push(stack, i * 10);
    }

    // 测试 Get_Stack_Length
    printf("栈的长度:%d\n", Get_Stack_Length(stack));

    // 测试 Get_Stack_Top
    int data;
    Get_Stack_Top(stack,&data);

    // 测试 Print_Stack
    Print_Stack(stack);

    // 测试 Pop
    printf("出栈3个元素\n");
    for (int i = 0; i < 3; i++) {
        Pop(stack,&data);
    }

    // 测试 Pop 后的 Get_Stack_Length
    printf("Pop 后栈的长度:%d\n", Get_Stack_Length(stack));

    // 测试 Pop 后的 Print_Stack
    printf("Pop 后栈的内容:\n");
    Print_Stack(stack);

    // 测试 Clear_Stack
    printf("清空栈\n");
    Clear_Stack(stack);

    // 测试 Clear_Stack 后的 Get_Stack_Length
    printf("Clear_Stack 后栈的长度:%d\n", Get_Stack_Length(stack));
    Print_Stack(stack);

    // 测试 Clear_Stack 后的 Stack_Is_Empty
    if (Stack_Is_Empty(stack)) {
        printf("Clear_Stack 后栈为空。\n");
    }
    else {
        printf("Clear_Stack 后栈不为空。\n");
    }

    // 测试 Destory_Stack
    printf("销毁栈\n");
    stack = Destory_Stack(stack);
    Print_Stack(stack);

    return 0;
}
(4)运行结果

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值