本文章利用C语言,实现了基于结构体元素的栈,主要功能包括:栈初始化、判断栈空、清除栈中所有元素、出栈、入栈、判断栈满、读取栈顶元素、栈中当前元素个数、多次出栈、栈元素反转、栈顶元素唯一入栈、栈搜索、栈当前容量。
栈作为一个最简单的数据结构,实现起来也非常容易,想想现在有一摞盘子,每次只能取走或放一个盘子且只能最上面进行操作;
本文主要包括三种栈:栈容量固定栈、可以扩大容量的栈、既可以扩大也可以缩小容量的栈。分别如下图所示:
主要的函数定义如下:
具体的C语言代码如下:
#ifndef STACK_H
#define STACK_H
#include <stdbool.h>
// Please do not change anything in header file //
// struct definition for each element in stack
struct Element {
int key;
char* value;
};
typedef struct Element Element;
// struct definition for stack
struct Stack {
int top;
int capacity;
float growthFactor;
float shrinkFactor;
bool dynamic;
Element** elements;
};
typedef struct Stack Stack;
// set of functions for stack
Stack* makeStack(int cap);
Stack* makeStackG(int cap, float growF);
Stack* makeStackGnS(int cap, float growF, float shrinkF);
Element* pop(Stack* s);
Element** multiPop(Stack* s, int k);
bool push(Stack* s, int k, char* v);
bool pushUnique(Stack* s, int k, char* v);
void reverse(Stack* s); // resizable
Element* peek(Stack* s);
int search(Stack* s, int k, char* v);
int getCapacity(Stack* s);
bool isFull(Stack* s);
void clear(Stack* s);
void cleanStack(Stack* s);
int currentSize(Stack* s);
bool isEmpty(Stack* s);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "stack.h"
// Edit only after this line //
//struct Stack stack;
// pop function for stack
Element* pop(Stack* s){
float filledRatio=1.0*currentSize(s)/getCapacity(s);
if (isEmpty(s))
return NULL;
if(s->dynamic) {
if( s->shrinkFactor > 0.0 && filledRatio<=s->shrinkFactor ) {
int newcapacity = (int)(s->capacity*0.5);
s->capacity = newcapacity;
s->elements = realloc(s->elements, sizeof(Element*)*newcapacity);
Element* e=s->elements[s->top-1];
//free(s->elements[s->top-1]);
s->top--;
return e;
}
else {
Element* e=s->elements[s->top-1];
free(s->elements[s->top-1]);
s->top--;
return e;
}
}
else{
Element* e=s->elements[s->top-1];
free(s->elements[s->top-1]);
s->top--;
return e;
}
}
// multipop: pop multiple elements from stack
Element** multiPop(Stack* s, int k){
int curr=currentSize(s);
Element** E= malloc(sizeof(Element*)*curr);
//int i=0;
if(isEmpty(s))
return NULL;
if(k<curr ){
for(int i=0; i<k; i++ ){
for(int j=curr; j>(curr - k); j--){
E[i]= s->elements[j];
}
pop(s);
}
}
else{
for(int i=0; i<curr; i++ ){
for(int j=curr; j >= 0; j--){
E[i]= s->elements[j];
}
pop(s);
}
}
return E;
}
// Utility function: add element for push
// This function is a hint, you may ignore its implementation
void addE(Stack* s, int k, char* v) {
}
// Utility function: expandCapacity for push
// This function is a hint, you may ignore its implementation
void expandCapacity(Stack* s) {
}
// push function for stack
bool push(Stack* s, int k, char* v){
Element* element = malloc(sizeof(Element));
element->key = k;
element->value = v;
//float filledRatio=0.0;
//if (getCapacity(s)>0)
float filledRatio=1.0*currentSize(s)/getCapacity(s);
//if (s->growthFactor>0)
if(isFull(s)){
return false;
}
if(s->dynamic){
if(s->growthFactor>0.0 && filledRatio >= s->growthFactor) {
int newcapacity = (int)(2*(s->capacity));
s->elements = realloc(s->elements, sizeof(Element*)*newcapacity);
s->capacity = newcapacity;
s->elements[s->top] = element;
s->top++;
return true;
}
else {
s->elements[s->top] = element;
s->top++;
return true;
}
}
else{
s->elements[s->top] = element;
s->top++;
return true;
}
}
// push unique function for stack
bool pushUnique(Stack* s, int k, char* v){
Element* e=peek(s);
if(e->key==k && e->value==v){
return false;
}
else {
if(push(s,k,v)){
return true;
}
else{
return false;
}
}
}
// reverse the elements in stack
void reverse(Stack* s){
int cap=s->top;
Element** E=multiPop(s,s->top);
int j;
for(j=0; j<cap; j++) {
push(s,E[j]->key,E[j]->value);
}
}
// peek function for stack
Element* peek(Stack* s){
if (isEmpty(s)) {
return NULL;
}
else {
return s->elements[s->top-1];
}
}
// search for element from top of stack
int search(Stack* s, int k, char* v){
int size=currentSize(s);
int i;
for(i=0; i<size; i++) {
if (s->elements[s->top-1-i]->key==k && s->elements[s->top-1-i]->value==v) {
return i+1;
}
}
return -1;
}
// get current capacity of stack
int getCapacity(Stack* s){
return s->capacity;
}
//check if stack is full
bool isFull(Stack* s){
if(s->top == getCapacity(s)) {
return true;
}
else
return false;
}
// clear the stack
void clear(Stack *s) {
s->top=0;
}
// clean the stack
void cleanStack(Stack *s) {
for(int i = 0; i < s->capacity; i++) {
free(s->elements[i]);
}
free(s->elements);
free(s);
}
// current size of stack
int currentSize(Stack* s){
return s->top;
}
// check if stack empty
bool isEmpty(Stack* s){
if (s->top==0)
return true;
else
return false;
}
// Stack with fixed capacity
Stack* makeStack(int cap){
Stack*s = malloc(sizeof(Stack));
s->top=0;
s->capacity = cap;
s->growthFactor=0.0;
s->shrinkFactor=0.0;
s->dynamic=false;
s->elements = malloc(sizeof(Element*)*cap);
return s;
}
// Stack that can grow,0.5<=growF<=1.0
Stack* makeStackG(int cap, float growF){
Stack*s = malloc(sizeof(Stack));
s->top=0;
s->capacity = cap;
s->growthFactor=growF;
s->shrinkFactor=0.0;
s->dynamic=true;
s->elements = malloc(sizeof(Element*)*cap);
return s;
}
// Stack that can grow and shrink
// 0.5<=growF<=1.0, 0 < shrinkF <= 0.5
Stack* makeStackGnS(int cap, float growF, float shrinkF){
Stack*s = malloc(sizeof(Stack));
s->top=0;
s->capacity = cap;
s->growthFactor=growF;
s->shrinkFactor=shrinkF;
s->dynamic=true;
s->elements = malloc(sizeof(Element*)*cap);
return s;
}
// print stack item list
void printStack(Stack* s){
printf("Stack item list:\n");
int i;
for(i=0; i< s->top; i++) {
printf("item:(%d,%s)\n",s->elements[s->top-1-i]->key,s->elements[s->top-1-i]->value);
}
}
int main(int argc, const char* argv[]) {
Stack*s=makeStack(5);
//makeStackG(5,0.5);
//Stack* s = makeStackGnS(5,0.7,0.3);
isEmpty(s);
push(s,1,"aaa");
printf("s->elements[0]:%d %s\n",s->elements[0]->key,s->elements[0]->value);
push(s,2,"bbb");
printf("s->elements[1]:%d %s\n",s->elements[1]->key,s->elements[1]->value);
push(s,4,"ddd");
push(s,5,"eee");
push(s,6,"fff");
push(s,7,"ggg");
push(s,8,"hhh");
printStack(s);
pushUnique(s,5,"eee");
pop(s);
pop(s);
peek(s);
pushUnique(s,5,"eee");
multiPop(s,3);
printStack(s);
reverse(s);
printStack(s);
search(s,3,"ccc");
search(s,2,"fcc");
clear(s);
isEmpty(s);
return 0;
}