用双向链表实现栈(C)

目录

一.结构定义:

二.结构操作

三.测试代码

四.运用


一.结构定义:

1.定义节点,包括一个前驱指针,一个后继指针,一个数据域

2.定义栈,包括一个栈顶指针,指向栈顶元素;一个栈所含元素个数size

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int STDataType;
//定义各个节点
typedef struct StackNode {
    struct Stack* next;
    struct Stack* prev;
    STDataType data;
}STNode;
//定义一个栈
typedef struct Stack {
    STNode* top;
    int size;
}Stack;

二.结构操作

包含初始化,入栈,出栈,查看栈顶元素,销毁栈,判空等操作。

void StackInit(Stack* ps);

void StackDestroy(Stack* ps);

void StackPush(Stack* ps, STDataType x);

void StackPop(Stack* ps);

STDataType StackTop(Stack* ps);

bool StackEmpty(Stack* ps);

int StackSize(Stack* ps);

具体实现如下:

void StackInit(Stack* ps) {
	assert(ps);
	ps->size = 0;
	ps->top = NULL;
}
void StackPush(Stack* ps, STDataType x) {
	assert(ps);
	STNode*newnode= (STNode*)malloc(sizeof(STNode));
	assert(newnode);
	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;
	if (ps->top == NULL)ps->top = newnode;
	else {
		ps->top->next = newnode;
		newnode->prev = ps->top;
		ps->top = newnode;
	}
	ps->size++;
}
void StackPop(Stack* ps) {
	assert(ps&&ps->top);
	if (ps->top->prev== NULL) {
		free(ps->top);
		ps->top = NULL;
	}
	else {
		STNode* prev = ps->top->prev;
		free(ps->top); 
		ps->top = prev;
	}
	ps->size--;
}
STDataType StackTop(Stack* ps) {
	assert(ps && ps->top);
	return ps->top->data;
}
bool StackEmpty(Stack* ps){
	assert(ps);
	return ps->top == NULL;
}
int StackSize(Stack* ps) {
	return ps->size;
}
void StackDestroy(Stack* ps) {
	assert(ps);
	while (ps->top) {
		StackPop(ps);
	}
}

三.测试代码

测试代码如下:

 测试结果如下:

四.运用

解LeetCode20.有效的括号:

 创建一个栈,遇到左括号入栈,遇到相同右括号出栈。

 代码实现:

typedef char STDataType;
typedef struct StackNode {
    struct Stack* next;
    struct Stack* prev;
    STDataType data;
}STNode;
typedef struct Stack {
    STNode* top;
    int size;
}Stack;
void StackInit(Stack* ps) {
	assert(ps);
	ps->size = 0;
	ps->top = NULL;
}
void StackPush(Stack* ps, STDataType x) {
	assert(ps);
	STNode*newnode= (STNode*)malloc(sizeof(STNode));
	assert(newnode);
	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;
	if (ps->top == NULL)ps->top = newnode;
	else {
		ps->top->next = newnode;
		newnode->prev = ps->top;
		ps->top = newnode;
	}
	ps->size++;
}
void StackPop(Stack* ps) {
	assert(ps&&ps->top);
	if (ps->top->prev== NULL) {
		free(ps->top);
		ps->top = NULL;
	}
	else {
		STNode* prev = ps->top->prev;
		free(ps->top); 
		ps->top = prev;
	}
	ps->size--;
}
STDataType StackTop(Stack* ps) {
	assert(ps && ps->top);
	return ps->top->data;
}
bool StackEmpty(Stack* ps){
	assert(ps);
	return ps->top == NULL;
}
int StackSize(Stack* ps) {
	return ps->size;
}
void StackDestroy(Stack* ps) {
	assert(ps);
	while (ps->top) {
		StackPop(ps);
	}
}
//以上是栈结构和操作定义。
bool isValid(char * s){
    if(s==NULL)return false;
    Stack st;
    StackInit(&st);
   while(*s!='\0'){
      if(*s=='('||*s=='{'||*s=='['){
          StackPush(&st,*s);
      }else{
          if(StackEmpty(&st)){//若第一个元素是右括号
            StackDestroy(&st);
            return false;     
          }
          if((StackTop(&st)=='('&&*s==')')||(StackTop(&st)=='['&&*s==']')||(StackTop(&st)=='{'&&*s=='}')){
              StackPop(&st);//出栈
          }else{
              StackDestroy(&st);
              return false;
          }
      }
      s++;
   }
   if((&st)->top!=NULL){//若栈顶还有元素
        StackDestroy(&st);
        return false;
   }
   StackDestroy(&st);
   return true;
}

链式存储的可以通过双向链表实现双向链表是一种数据结构,其中每个节点都包含一个指向前驱节点和后继节点的指针。是一种具有后进先出(LIFO)特性的数据结构,可以在链表的头部进行插入和删除操作。 下面是使用双向链表实现链式存储的的示例代码(使用C++语言): ```cpp #include <iostream> // 定义双向链表节点结构体 struct Node { int data; // 数据 Node* prev; // 前驱节点指针 Node* next; // 后继节点指针 Node(int val) : data(val), prev(nullptr), next(nullptr) {} }; // 定义链式存储的类 class Stack { private: Node* top; // 顶指针 public: Stack() : top(nullptr) {} // 判断是否为空 bool isEmpty() { return top == nullptr; } // 入操作 void push(int val) { Node* newNode = new Node(val); if (isEmpty()) { top = newNode; } else { newNode->next = top; top->prev = newNode; top = newNode; } std::cout << val << " 入成功!" << std::endl; } // 出操作 int pop() { if (isEmpty()) { std::cout << "为空,无法进行出操作!" << std::endl; return -1; // 返回一个特殊值表示出错 } int val = top->data; Node* temp = top; if (top->next != nullptr) { top = top->next; top->prev = nullptr; } else { top = nullptr; } delete temp; std::cout << val << " 出成功!" << std::endl; return val; } // 获取顶元素 int getTop() { if (isEmpty()) { std::cout << "为空,无法获取顶元素!" << std::endl; return -1; // 返回一个特殊值表示出错 } return top->data; } }; int main() { Stack stack; stack.push(10); stack.push(20); stack.push(30); std::cout << "顶元素为:" << stack.getTop() << std::endl; stack.pop(); stack.pop(); std::cout << "顶元素为:" << stack.getTop() << std::endl; stack.pop(); return 0; } ``` 这个示例中,我们使用双向链表的头部作为顶,并且在入操作时将新节点插入链表的头部,出操作时删除链表的头部节点。通过双向链表的前驱和后继指针,我们可以方便地在链表头部进行插入和删除操作,并且可以随时获取顶元素。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值