数据结构--第四天

--栈

        -栈的概念

           栈:一种特殊的线性表,只允许在栈顶进行插入和删除元素操作,即“头删头插”,栈的这种特性使它在处理递归性质的问题和算法中非常有用

        -栈的特点

        1.后进先出:栈的基本操作确保了最后被添加的元素总是被第一个删除

        2.单端操作:所有的添加和移除操作仅在栈的同一端进行,这一端被称为栈顶,另一端被称为栈底

栈操作图示:

        -链式栈

                链式栈概念

                  链式栈:插入操作和删除操作均在链表头部进行,链表尾部就是栈底栈顶指针就是链表的头指针

                 本质:栈顶指针+链表

        -链式栈示例代码

                main.c
#include "stack.h"
void menu();
int main(){
	int select;
	stack_t* stack = NULL;
	do{
		menu();
		printf("请选择:");
		scanf("%d",&select);
		switch(select){
			case 1:
				if(stack==NULL){
					stack_init(&stack);
				}
				pop(stack);
				break;
			case 2:
				if(stack==NULL){
					stack_init(&stack);
				}
				push(stack);
				break;
			case 3:
				stack_is_empty(stack);
				break;
			case 4:
				display_stack_top(stack);
				break;
			case 5:
				clear_stack(&stack);
				exit(EXIT_FAILURE);
				break;
		}
	}while(1);
	return 0;
}

void menu(){
	printf("---------stack---------\n");
	printf("1.出栈 pop\n");
	printf("2.入栈 push\n");
	printf("3.判断栈是否为空\n");
	printf("4.查看栈顶元素\n");
	printf("5.退出\n");
	printf("---------END-----------\n");
}
        stack.c
#include "stack.h"

void stack_init(stack_t** stack){
	stack_t* p_stack=(stack_t*)malloc(sizeof(stack_t));
	if(p_stack==NULL){
		printf("malloc failure.\n");
		return;
	}
	p_stack->size=0;
	linkedlist_init(&(p_stack->head));
	*stack=p_stack;

}

void push(stack_t* stack){
        datatype_t* stu=(datatype_t*)malloc(sizeof(datatype_t));
        if(stu==NULL){
                printf("malloc failure:%s\n",strerror(errno));
                printf("入栈失败\n");
                return;
        }
        memset(stu,0,sizeof(datatype_t));
        while(getchar()!='\n');
        printf("请输入姓名:");
        fgets(stu->name,sizeof(stu->name)-1,stdin);
        stu->name[strlen(stu->name)-1]='\0';
        printf("请输入id:");
        fgets(stu->id,sizeof(stu->id)-1,stdin);
        stu->id[strlen(stu->id)-1]='\0';
        bool res=linkedlist_insert_head(stack->head,stu);
        if(res){
		stack->size++;
                printf("入栈成功\n");
        }else{
                printf("入栈失败\n");
        }
}

void stack_is_empty(stack_t* stack){
        if(stack==NULL || stack->size==0){
                printf("栈为空\n");
        }else{
                printf("栈不为空\n");
        }
}

void pop(stack_t* stack){
        datatype_t* res=linkedlist_remove_head(stack->head);
        if(res==NULL){
                printf("没有数据!\n");
                return;
        }
        printf("姓名:%s,学号:%s\n",res->name,res->id);
        free(res);
        res=NULL;
	stack->size--;
}

void clear_stack(stack_t** stack){
        linkedlist_clean(&((*stack)->head));
	free(*stack);
	*stack=NULL;
}

void display_stack_top(stack_t* stack){
        datatype_t* res=linkedlist_get_headdata(stack->head);
        if(res==NULL){
                printf("栈为空\n");
                return;
        }
        printf("stack top:\n");
        printf("姓名:%s,学号:%s\n",res->name,res->id);
}
        stack.h
#ifndef __HEAD_STACK_H__
#define __HEAD_STACK_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include "linkedlist.h"

typedef struct{
	node_t* head;
	int size;
}stack_t;

extern void stack_init(stack_t** stack);
extern void push(stack_t*);
extern void display_stack_top(stack_t*);
extern void stack_is_empty(stack_t*);
extern void pop(stack_t*);
extern void clear_stack(stack_t**);

#endif
        linkedlist.c
#include "linkedlist.h"

void linkedlist_init(node_t** p_head){
        node_t* p_node = (node_t*)malloc(sizeof(node_t));
        if(p_node==NULL){
                printf("malloc failure:%s\n",strerror(errno));
                return;
        } 
        memset(p_node,0,sizeof(node_t));
        p_node->next = *p_head;
	*p_head = p_node;
}

// 添加的方法
bool linkedlist_insert_head(node_t* p_head,datatype_t* val){
	//将data添加到链表的头部
	// 1、封装成节点
	node_t* p_node = (node_t*)malloc(sizeof(node_t));
	if(p_node==NULL){
		printf("malloc failure:%s\n",strerror(errno));
		return false;
	}
	memset(p_node,0,sizeof(node_t));
	p_node->data = val;
	p_node->next = NULL;
	// 2、改变指针的指向
	p_node->next = p_head->next;
	p_head->next = p_node;
	return true;
}

// 打印链表中所有的结点数据
void linkedlist_display(node_t* head){
	node_t* cur = head->next;
	if(cur==NULL){
		printf("栈为空\n");
		return;
	}
		printf("[name:%s,id:%s]-->",cur->data->name,cur->data->id);
}

bool linkedlist_is_empty(node_t* head){
	return head==NULL || (head->next==NULL?true:false);
}
// 删除节点根据值
datatype_t* linkedlist_remove_head(node_t* head){
	if(linkedlist_is_empty(head)){
		return NULL;
	}else{
		node_t* delnode = head->next;
		datatype_t* data=delnode->data;
		head->next = head->next->next;
		free(delnode);
		delnode=NULL;
		return data;
	}
}

void linkedlist_clean(node_t** head){
	if(*head == NULL){
                return;
        }

	node_t* pre = *head;
	while(pre->next!=NULL){
		node_t* delnode = pre->next;
		pre->next = pre->next->next;
		free(delnode);
		delnode=NULL;
	}
	free(*head);
	*head= NULL;
}
datatype_t* linkedlist_get_headdata(node_t* head){
	if(linkedlist_is_empty(head)){
		return NULL;
	}else{
		return head->next->data;
	}
}
linkedlist.h
#ifndef __HEAD_LINKED_LIST_H__
#define __HEAD_LINKED_LIST_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>

typedef struct{
	char id[128];
	char name[128];
}datatype_t;

//  定义结构体类型
typedef struct Node{
	// 数据域
	datatype_t* data;
	// 指针域
	struct Node* next;
}node_t;

extern bool linkedlist_insert_head(node_t* p_head,datatype_t* val);
extern void linkedlist_display(node_t* head); 
extern void linkedlist_init(node_t** p_head);
extern bool linkedlist_is_empty(node_t* head);
extern datatype_t* linkedlist_remove_head(node_t* head);
extern void linkedlist_clean(node_t** head);
extern datatype_t* linkedlist_get_headdata(node_t*);
#endif
输出结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值