c/c++ 栈实现
关于Harsha Suryanarayana:
https://www.freecodecamp.org/chinese/news/mycodeschool-youtube-channel-history/
B站视频:
【【强烈推荐】深入浅出数据结构 - 顶尖程序员图文讲解 - UP主翻译校对 (已完结)】https://www.bilibili.com/video/BV1Fv4y1f7T1?vd_source=2cb4b275b46b9a0bd5d3d0e3d51588e6
油管:
https://www.youtube.com/watch?v=92S4zgXN17o&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P
仓库:
GitHub:https://github.com/LIangZH-RT/data_structure_code
gitee:https://gitcode.com/LangZH_RT/data_structure_code/tree/main
Stack栈
第一个为叠盘。
第二个为汉诺塔,是一个数学问题,你在学习递归时可能会遇到这个问题。
第三个就是一个筒里装有一些球。
上面这些图都有一个特性:放的时候第一个总是会被压到最底,你只能拿到最上面的物品。放入的时候那个物品总是在最顶上,最后放入的总是最先被拿走。
栈就是如此,它遵循一个原则:后进先出(Last-In-First-Out),这是它的一个限制。插入、删除元素只能从一端进行,我们称那一端为栈顶。 插入栈的操作为push,“推入栈中”。删除操作为pop,“弹出栈”。当然还有一些别的操作:top(栈顶元素),isEmpty(是否空栈)。
但是要注意:它的所有操作时间复杂度都是O(1)。
栈可以这样来表示,只有一个开口的容器:
之前在链表反转的时候提到过,它可以用来呈现出函数的执行过程。
栈实现1(第一种数组实现)
栈结构1
栈可以用数组来实现,数组的插入,访问效率很高,它是指针偏移的方式直接到位。
那就先声明一个数组,给出top(用于标记栈顶):
int arr[10] = {0}; //当然也可不赋值
int top = -1; //一开始top为-1
栈操作–插入(推入)push
push一个元素会把top向右移一位,直接到数组首位,这就是为什么一开始top = -1。
写一下代码,这里需要前置++,先加再使用:
void push(int data){
arr[++top] = data;
}
两步操作:右移top,再给top位置赋值。
栈操作–删除(弹出)pop
删除操作仅需把top左移,当然这里不需要把2位置的赋值5给去掉,你去掉,需多添一行代码。但是呢那个位置还是要占相对应的内存,没有意义。
**注意:如果栈为空top就是-1,在没有处理空栈的情况下使用pop会让top=-2,下一次插入元素就是插入到-1位置,发生错误。**所以需要判断:
void pop(){
if(top == -1) printf("Empty Stack\n");
else top--;
}
栈操作–top栈顶
直接返回top对应元素即可,但需要注意,top为-1会造成数组访问错误,需要处理特殊情况。
void Top(){
if(top == -1) {printf("Empty Stack\n");return;}
else ptintf("%d",arr[top]);
}
栈操作–isEmpty栈空判断
返回一个bool或者在控制台输出Stack的情况。以top的值判断,空栈top = -1。
bool isEmpty(){
if(top == -1) return false;
else return true;
}
栈满
在栈满的情况下,如果还要插入,就需要扩大数组大小。具体过程为:再开一个大数组,把原来数组内容复制进大数组。这样插入时间复杂度就是O(n)。
以下为使用链表实现,Stack由链表衍生而出,加了后进先出的限制。
栈实现2(第二种链表实现)
使用链表实现,可以节省空间,并且空间没有直接限制,可加到内存满。
插入push
链表实现Stack,由于链表的pushback操作时间复杂度为O(n),所以在插入元素时不再是像尾部插入。头插时间复杂为O(1),使用头插,栈顶元素自然就是第一个节点。重复之前链表操作,实现:
typedef struct Node{
struct Node *next;
int data;
}Node;
Node* createNode(int data){
Node * temp = (Node*)malloc(sizeof(Node));
temp->data = data;
temp->next = NULL;
return temp;
}
void push(Node ** top,int data){
Node * temp = createNode(data);
temp->next = *top;
*top = temp;
}
删除pop
每次插入都是头位置,也就是栈顶,所以删除就是删除头元素。复刻链表操作:
void pop(Node** top){
if(*top == NULL) return;
Node * temp = *top;
*top = (*top)->next;
free(temp);
}
返回栈顶元素Top
输出top的元素:
void Top(Node * top){
if(top == NULL) {printf("Empty!\n");return;}
printf("%d",top->data);
}
栈空判断isEmpty
同样为使用top判断:
void isEmpty(Node * top){
if(top == NULL) printf("Empty Stack\n");
else printf("NOT EMPTY\n");
}
结语
Stack实现到此结束,后续会出Stack的作用,反转、检查等。
如果您发现内容存在疑问或错误,欢迎私信或评论,个人邮箱:aa2961363680@outlook.com。