스택을 구현하는 방법에는 3가지가 있습니다. 1. 구조체의 길이를 고정해야 하는 정적 배열 스택, 컴파일 타임에 길이를 결정해야 함. 길이는 런타임에 결정되고 변경될 수 있습니다. 3. 온라인 길이가 없는 체인 구조 스택은 필요할 때 메모리 공간 할당을 적용합니다.
스택을 구현하는 방법에는 3가지가 있습니다. 구현 방법은 다음과 같습니다.
1. 정적 배열 스택
정적 배열 스택에서 STACK_SIZE
는 크기를 나타냅니다. 스택이 저장할 수 있는 요소의 최대값입니다. top_element
를 배열 첨자로 사용하여 스택의 요소를 나타냅니다. top_element == -1
인 경우 스택이 비어 있습니다. top_element == STACK_SIZE - 1
이면 스택이 가득 찼음을 의미합니다. 푸시할 때 top_element
는 1씩 증가합니다. top_element == 0
이면 팝할 때 첫 번째 스택 요소를 나타내고 top_element
는 1씩 감소합니다. STACK_SIZE
表示堆栈所能存储的元素的最大值,用top_element
作为数组下标来表示堆栈里面的元素,当top_element == -1
的时候表示堆栈为空;当top_element == STACK_SIZE - 1
的时候表示堆栈为满。push的时候top_element
加1,top_element == 0
时表示第一个堆栈元素;pop的时候top_element
减1。
a_stack.c 源代码如下:
[cpp] view plain copy /* ** ** 静态数组实现堆栈程序 a_stack.c ,数组长度由#define确定 */ #include"stack.h" #include<assert.h> #include<stdio.h> #define STACK_SIZE 100 /* 堆栈最大容纳元素数量 */ /* ** 存储堆栈中的数组和一个指向堆栈顶部元素的指针 */ static STACK_TYPE stack[STACK_SIZE]; static int top_element = -1; /* push */ void push(STACK_TYPE value) { assert(!is_full()); /* 压入堆栈之前先判断是否堆栈已满*/ top_element += 1; stack[top_element] = value; } /* pop */ void pop(void) { assert(!is_empty()); /* 弹出堆栈之前先判断是否堆栈已空 */ top_element -= 1; } /* top */ STACK_TYPE top(void) { assert(!is_empty()); return stack[top_element]; } /* is_empty */ int is_empty(void) { return top_element == -1; } /* is_full */ int is_full(void) { return top_element == STACK_SIZE - 1; } /* ** 定义一个print函数,用来打印堆栈里面的元素。 */ void print(void) { int i; i = top_element; printf("打印出静态数组堆栈里面的值: "); if(i == -1) printf("这是个空堆栈\n"); while(i!= -1) printf("%d ",stack[i--]); printf("\n"); } int main(void) { print(); push(10); push(9); push(7); push(6); push(5); push(4); push(3); push(2); push(1); push(0); printf("push压入数值后:\n"); print(); printf("\n"); pop(); pop(); printf("经过pop弹出几个元素后的堆栈元素:\n"); print(); printf("\n"); printf("top()调用出来的值: %d\n",top()); return 1; }
结果如下图:
二、动态数组堆栈
头文件还是用stack.h
,改动的并不是很多,增加了stack_size
变量取代STACK_SIZE
来保存堆栈的长度,数组由一个指针来代替,在全局变量下缺省为0。
create_stack
函数首先检查堆栈是否已经创建,然后才分配所需数量的内存并检查分配是否成功。destroy_stack
函数首先检查堆栈是否存在,已经释放内存之后把长度和指针变量重新设置为零。is_empty
和 is_full
函数中添加了一条断言,防止任何堆栈函数在堆栈被创建之前就被调用。
d_stack.c
源代码如下:
[cpp] view plain copy /* ** 动态分配数组实现的堆栈程序 d_stack.c ** 堆栈的长度在创建堆栈的函数被调用时候给出,该函数必须在任何其他操作堆栈的函数被调用之前条用。 */ #include"stack.h" #include<stdio.h> #include<malloc.h> #include<assert.h> /* ** 用于存储堆栈元素的数组和指向堆栈顶部元素的指针 */ static STACK_TYPE *stack; static int stack_size; static int top_element = -1; /* create_stack */ void create_stack(size_t size) { assert(stack_size == 0); stack_size = size; stack = (STACK_TYPE *)malloc(stack_size * sizeof(STACK_TYPE)); if(stack == NULL) perror("malloc分配失败"); } /* destroy */ void destroy_stack(void) { assert(stack_size > 0); stack_size = 0; free(stack); stack = NULL; } /* push */ void push(STACK_TYPE value) { assert(!is_full()); top_element += 1; stack[top_element] = value; } /* pop */ void pop(void) { assert(!is_empty()); top_element -= 1; } /* top */ STACK_TYPE top(void) { assert(!is_empty()); return stack[top_element]; } /* is_empty */ int is_empty(void) { assert(stack_size > 0); return top_element == -1; } /* is_full */ int is_full(void) { assert(stack_size > 0); return top_element == stack_size - 1; } /* ** 定义一个print函数,用来打印堆栈里面的元素。 */ void print(void) { int i; i = top_element; printf("打印出动态数组堆栈里面的值: "); if(i == -1) printf("这是个空堆栈\n"); while(i!= -1) printf("%d ",stack[i--]); printf("\n"); } int main(void) { create_stack(50); print(); push(10); push(9); push(7); push(6); push(5); push(4); push(3); push(2); push(1); push(0); printf("push压入数值后:\n"); print(); printf("\n"); pop(); pop(); printf("经过pop弹出几个元素后的堆栈元素:\n"); print(); printf("\n"); printf("top()调用出来的值: %d\n",top()); destroy_stack(); return 1; }
结果如下图:
三、链式堆栈
由于只有堆栈顶部元素才可以被访问,因此适用单链表可以很好实现链式堆栈,而且无长度限制。把一个元素压入堆栈是通过在链表头部添加一个元素实现。弹出一个元素是通过删除链表头部第一个元素实现。由于没有长度限制,故不需要create_stack
函数,需要destroy_stack
进行释放内存以避免内存泄漏。
头文件stack.h
不变,l_stack.c
[cpp] view plain copy /* ** 单链表实现堆栈,没有长度限制 */ #include"stack.h" #include<stdio.h> #include<malloc.h> #include<assert.h> #define FALSE 0 /* ** 定义一个结构以存储堆栈元素。 */ typedef struct STACK_NODE { STACK_TYPE value; struct STACK_NODE *next; } StackNode; /* 指向堆栈中第一个节点的指针 */ static StackNode *stack; /* create_stack */ void create_stack(size_t size) {} /* destroy_stack */ void destroy_stack(void) { while(!is_empty()) pop(); /* 逐个弹出元素,逐个释放节点内存 */ } /* push */ void push(STACK_TYPE value) { StackNode *new_node; new_node = (StackNode *)malloc(sizeof(StackNode)); if(new_node == NULL) perror("malloc fail"); new_node->value = value; new_node->next = stack; /* 新元素插入链表头部 */ stack = new_node; /* stack 重新指向链表头部 */ } /* pop */ void pop(void) { StackNode *first_node; assert(!is_empty()); first_node = stack; stack = first_node->next; free(first_node); } /* top */ STACK_TYPE top(void) { assert(!is_empty()); return stack->value; } /* is_empty */ int is_empty(void) { return stack == NULL; } /* is_full */ int is_full(void) { return FALSE; } /* ** 定义一个print函数,用来打印堆栈里面的元素。 */ void print(void) { StackNode *p_node; p_node = stack; printf("打印出链式堆栈里面的值: "); if(p_node == NULL) printf("堆栈为空\n"); while(p_node != NULL) { printf("%d ", p_node->value); p_node = p_node->next; } printf("\n"); } int main(void) { print(); push(10); push(9); push(7); push(6); push(5); push(4); push(3); push(2); push(1); push(0); printf("push压入数值后:\n"); print(); printf("\n"); pop(); pop(); printf("经过pop弹出几个元素后的堆栈元素:\n"); print(); printf("\n"); printf("top()调用出来的值: %d\n",top()); destroy_stack(); return 1; }결과는 아래와 같습니다. 🎜 헤더 파일은 여전히
stack.h
를 사용하고 있지만 변경 사항은 많지 않습니다. , 가 추가됩니다. stack_size
변수는 스택 길이를 저장하기 위해 STACK_SIZE
를 대체합니다. 배열은 전역 변수에서 기본값이 0인 포인터로 대체됩니다. 🎜🎜 create_stack
함수는 먼저 스택이 생성되었는지 확인한 후 필요한 양의 메모리를 할당하고 할당이 성공했는지 확인합니다. destroy_stack
함수는 먼저 스택이 존재하는지 확인하고 메모리가 해제된 후 길이 및 포인터 변수를 0으로 재설정합니다. 스택이 생성되기 전에 스택 함수가 호출되는 것을 방지하기 위해 is_empty
및 is_full
함수에 어설션이 추가되었습니다. 🎜🎜d_stack.c
소스 코드는 다음과 같습니다. 🎜rrreee🎜 결과는 다음과 같습니다. 🎜🎜🎜🎜🎜3, 체인 스택🎜🎜🎜 스택의 최상위 요소에만 접근할 수 있으므로, 단일 연결 리스트는 길이 제한 없이 체인 스택을 매우 잘 구현하는 데 사용될 수 있습니다. 요소를 스택에 푸시하는 것은 연결 목록의 헤드에 요소를 추가하여 수행됩니다. 요소 팝핑은 연결된 목록의 첫 번째 요소를 삭제하여 수행됩니다. 길이 제한이 없으므로 create_stack
함수는 필요하지 않으며, 메모리 누수를 방지하기 위해 메모리를 해제하려면 destroy_stack
이 필요합니다. 🎜🎜헤더 파일 stack.h
는 변경되지 않고 그대로 유지되며, l_stack.c
의 소스 코드는 다음과 같습니다. 🎜rrreee🎜 결과는 아래와 같습니다. 🎜🎜🎜🎜 🎜추천 튜토리얼: "🎜java video Tutorial🎜》🎜위 내용은 스택을 구현할 수 있는 방법은 몇 가지입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!