栈
栈满足下列两点:
1.栈只能从表的一端存取数据,另一端是封闭的。
2.在栈中,无论是存数据还是取数据,都必须遵循"先进后出"的原则,即最先进栈的元素最后出栈。
总结:栈是一种只能从表的一端存取数据且遵循 "先进后出" 原则的线性存储结构。
如图:栈存储结构存储
{1,2,3,4}
栈的顺序表实现:
顺序表就是采用数组+尾指针的方式,尾指针一直指向最后一个元素,这里特殊的地方在于,栈为空时,尾指针指向-1.
#include <stdio.h>
#define Size 100
typedef struct stacktag
{
int a[Size];
int top;
}stack;
#入栈
int rush(int* a,int top,int elem){
if(++top>=Size)
{
printf("栈已满\n");
return --top;
}
a[++top]=elem;
printf("插入元素:%d\n",a[top]);
return top;
}
#出栈
int pop(int * a,int top){
if (top==-1) {
printf("空栈");
return -1;
}
printf("弹栈元素:%d\n",a[top]);
top--;
return top;
}
int main () {
stack stack1;
stack1.top = -1;
printf("初始化成功\n");
stack1.top = rush(stack1.a,stack1.top,1);
stack1.top = rush(stack1.a,stack1.top,5);
stack1.top = pop(stack1.a,stack1.top);
return 0;
}
初始化成功
插入元素:1
插入元素:5
弹栈元素:5
栈的链表实现:
使用链表实现注意一点:
数据插入采用头插法,数据每次弹出头部的元素
#include <stdio.h>
#include<malloc.h>
//声明链表节点类型
typedef struct LISTtag LISTtagNode;
struct LISTtag{
int value;
LISTtagNode *next;
};
int size=0;
//创建链表
LISTtagNode * create(){
LISTtagNode *head;
head = (LISTtagNode*)malloc(sizeof(LISTtagNode));
head->next = NULL;
return head;
}
//在链表头新增节点
int push(LISTtagNode *head,int value){
if(head == NULL){
return -1;
}
//新建节点
LISTtagNode *node;
node = (LISTtagNode*)malloc(sizeof(LISTtagNode));
//节点赋值,此节点跟在头节点后
node->value = value;
node->next = head->next;
head->next = node;
size++;
return 1;
}
//打印链表
int PrindLinKList(LISTtagNode *head){
if(head == NULL){
return -1;
}
LISTtagNode *t = head;
while (t->next != NULL) {
t = t->next;
printf("%d ", t->value);
}
return 1;
}
int pop(LISTtagNode *head){
if(head ==NULL){
return -1;
}
LISTtagNode *node;
int index = 0;
while(head->next!=NULL&&index<1){
node = head->next;
index++;
}
if(index == 1){
printf("\n%d ",node->value);
if(head->next->next != NULL){
head->next = head->next->next;
}else{
head->next =NULL;
}
free(node);
size--;
return 1;
}
return -1;
}
int top(LISTtagNode *head){
if(head ==NULL){
return -1;
}
LISTtagNode *node;
int index = 0;
while(head->next!=NULL&&index<1){
node = head->next;
index++;
}
if(index == 1){
printf("%d ",node->value);
return 1;
}
return -1;
}
int empty(LISTtagNode *head){
if(head ==NULL){
return -1;
}
if(head->next!=NULL){
return 0;
}
return 1;
}
int length(LISTtagNode *head){
if(head ==NULL){
return -1;
}
return size;
}
int main () {
LISTtagNode *head = create();
push(head,7);
push(head,9);
push(head,23);
push(head,43);
push(head,45);
push(head,65);
printf("\n正序打印链表:");
PrindLinKList(head);
printf("\n链表长度:%d",length(head));
pop(head);
printf("\n正序打印链表:");
PrindLinKList(head);
printf("\n链表长度:%d",length(head));
return 0;
}
队列
队列满足下列两点:
1.队列从一端表存储数据,从另一端是读取数据。
2.数据的入队和出队遵循"先进先出"的原则;
总结:队列是一种从表的一端存储数据,从另一端读取数据,满足“先进先出”的数据结构。
队列的实现:
#include <stdio.h>
#define max 5//表示顺序表申请的空间大小
int enQueue(int *a,int front,int rear,int data){
//添加判断语句,如果rear超过max,则直接将其从a[0]重新开始存储,如果rear+1和front重合,则表示数组已满
if ((rear+1)%max==front) {
printf("空间已满");
return rear;
}
a[rear%max]=data;
rear++;
return rear;
}
int deQueue(int *a,int front,int rear){
//如果front==rear,表示队列为空
if(front==rear%max) {
printf("队列为空");
return front;
}
printf("%d ",a[front]);
//front不再直接 +1,而是+1后同max进行比较,如果=max,则直接跳转到 a[0]
front=(front+1)%max;
return front;
}
int main() {
int a[max];
int front,rear;
//设置队头指针和队尾指针,当队列中没有元素时,队头和队尾指向同一块地址
front=rear=0;
//入队
rear=enQueue(a,front,rear, 1);
rear=enQueue(a,front,rear, 2);
rear=enQueue(a,front,rear, 3);
rear=enQueue(a,front,rear, 4);
//出队
front=deQueue(a, front, rear);
//再入队
rear=enQueue(a,front,rear, 5);
//再出队
front=deQueue(a, front, rear);
//再入队
rear=enQueue(a,front,rear, 6);
//再出队
front=deQueue(a, front, rear);
front=deQueue(a, front, rear);
front=deQueue(a, front, rear);
front=deQueue(a, front, rear);
return 0;
}
1 2 3 4 5 6
使用环形表实现顺序队列的方法需要注意的是,顺序队列在判断数组是否已满时,出现下面情况:
- 当队列为空时,队列的头指针等于队列的尾指针;
- 当数组满员时,队列的头指针等于队列的尾指针;