目录
一、栈
(注意:本文章仅为个人笔记作用,无法保证绝对的准确性与规范性,仅保证程序实现算法需求)
1.栈的思想
栈是一种特殊的数据结构,一切数据只能在栈顶进出,不能像链表一样在头部或者中间插入删除。相对与链表的自由和灵活,栈显得更规范,更有针对性,比如递归的原理就是栈。
(学习链栈所需知识:链表的基本操作、指针的基础了解)
2.链栈的组成
【1】栈的结构
链栈由链表组成,以指针所指节点为栈顶
//数据域
typedef struct Node{
int num;//数据域可以包括更多东西,这里的int num仅用于讲解方便
struct Node *next;
}Node;
//链栈的结构体
typedef struct Stack{
Node *top;//栈顶
int cnt;//栈节点的个数
}Stack;
【2】栈的功能函数
(下面申请空间的语句如Node *node=new Node
C语言改为Node *node=(Node*)malloc( sizeof(Node) ) 即可,不影响程序正常使用)
(1)初始化链栈
因为链栈不需要头节点,故栈顶指针初始化为空即可
//栈初始化
int InitStack(Stack *s)
{
s->top=NULL;
s->cnt=0;
}
(2)链栈判断是否为空
直接判断s->top是否等于NULL即可,这里因为有记录栈元素的个数,也可以判断个数(如下)
//栈判空,空返回1
int StackEmpty(Stack *s)
{
if(s->cnt==0)
return 1;
else
return 0;
}
(3)求栈的长度
即求s->cnt为多少
//求栈的长度
int StackSize(Stack *s)
{
return s->cnt;
}
(4)求栈顶元素
//求栈顶元素
int TopData(Stack *s)
{
return s->top->num;
}
(5)进栈
申请一个新节点,把数据存进节点,再让该节点的指针指向栈顶元素,最后令栈顶指针指向新节点,栈的个数加一,完成进栈
//进栈
int Push(Stack *s,int data)
{
Node *node=new Node;
if(node==NULL)
return 0;
node->num=data;
node->next=s->top;
s->top=node;
s->cnt++;
return 1;
}
(6)出栈
创建一个新指针指向栈顶元素,保存栈顶信息,令栈顶指针指向栈顶的下一个元素,释放栈顶元素的空间,栈的个数减一,完成出栈
//出栈
int Pop(Stack *s,int *e)
{
Node *p=s->top;
s->top=s->top->next;
*e=p->num;
delete p;
s->cnt--;
return 1;
}
(7)遍历栈的内容
新建指针指向栈顶元素,打印信息并继续指向下一个元素,直至指针为空
//打印栈内容
void Show(Stack *s)
{
Node *p=s->top;
while(p){
cout<<"data="<<p->num<<endl;
p=p->next;
}
}
3.栈的全部代码
//栈
#include<iostream>
using namespace std;
typedef struct Node{
int num;
struct Node *next;
}Node;
typedef struct Stack{
Node *top;
int cnt;
}Stack;
//栈初始化
int InitStack(Stack *s)
{
s->top=NULL;
s->cnt=0;
}
//栈判空
int StackEmpty(Stack *s)
{
if(s->cnt==0)
return 1;
else
return 0;
}
//求栈顶元素
int TopData(Stack *s)
{
return s->top->num;
}
//求栈的长度
int StackSize(Stack *s)
{
return s->cnt;
}
//进栈
int Push(Stack *s,int data)
{
Node *node=new Node;
if(node==NULL)
return 0;
node->num=data;
node->next=s->top;
s->top=node;
s->cnt++;
return 1;
}
//出栈
int Pop(Stack *s,int *e)
{
Node *p=s->top;
s->top=s->top->next;
*e=p->num;
delete p;
s->cnt--;
return 1;
}
//打印栈内容
void Show(Stack *s)
{
Node *p=s->top;
while(p){
cout<<"data="<<p->num<<endl;
p=p->next;
}
}
int main()
{
Stack s;//这里不用指针形式的结构体,因为链表中head节点属于*node而s包含*top
//不属于指针节点,故不用指针形式
InitStack(&s);
for(int i=0;i<6;i++)
{
cout<<"进栈了元素:"<<i<<endl;
Push(&s,i);
}
cout<<"栈为空吗:"<<StackEmpty(&s)<<endl;
cout<<"栈的长度为:"<<s.cnt<<endl;
cout<<"栈顶元素为:"<<s.top->num<<endl;
cout<<"\n第一次遍历:\n";
Show(&s);
int a;
Pop(&s,&a);
cout<<"出栈元素a="<<a<<endl;
Pop(&s,&a);
cout<<"出栈元素a="<<a<<endl;
cout<<"\n第二次遍历:\n";
Show(&s);
}
二、队列
1.队列的思想
队列是一种只允许再一端插入和另一端删除的数据结构,模拟人们平时排队的情景,队头出队,队尾进队。
2.链队的结构
队头(front):插入数据的一端
队尾(rear):删除数据的一端
空队列:没有任何元素的空队
结构体:
typedef struct Node{//和链表的节点一样,用来存数据
int num;//这里是数据域,为了方便演示,数据域暂时定义为int型的数字
struct Node *next;
}Node;
//队链的q是一个结构体而不是指针结构体,故不用像链表一样设为*node,直接Queue q
typedef struct Queue{
struct Node *front,*rear;//队头和队尾
int cnt;//队列长度
}Queue;
3.链队的基本操作
初始化队列:void InitQueue(Queue *q)
队列判空:int Empty(Queue *q)
队列长度:int Size(Queue *q)
进队:int Push(Queue *q)
出队:int Pop(Queue *q)
遍历并展示队列:void Show(Queue *q)
4.链队代码实现
【1】初始化队列
链队需要一个头节点,便于删除队列的第一个元素,同时也能在该头节点记录队列长度等数据
//初始化队链
int InitQueue(Queue *q)
{
q->front=q->rear=new Node;
q->front->next=NULL;//和链表一样,头节点的next指针指向空
q->cnt=0;//队列长度初始化为0
}
【2】队列判空
当头指针和尾指针指在同一个节点(即头节点)时,队列为空,空则返回1,不空返回0
//判空
int QueueEmpty(Queue *q)
{
if(q->front==q->rear)
return 1;
else
return 0;
}
【3】队列长度
直接求cnt的值即可
//求队列的长度
int QueueSize(Queue *q)
{
return q->cnt;
}
【4】进栈
同等于链表的尾插法,头指针(front)不移动,尾指针(rear)指向当前尾指针的下一个元素(即新插入的元素)
//进队
int Push(Queue *q,int data)
{
Node *node=new Node;
node->num=data;
node->next=NULL;
q->rear->next=node;
q->rear=node;
q->cnt++;
}
【5】出队
删除头节点的下一个元素(即第一个元素),同链表删除第一个元素一样,但要注意,当队列仅剩一个元素时,要把尾指针(rear)指在头节点,不然尾指针会丢失
//出队
int Pop(Queue *q,int *e)
{
Node *p=q->front->next;
*e=p->num;
q->front->next=p->next;
if(p==q->rear){
q->rear=q->front;
}
delete p;
q->cnt--;
}
【6】遍历并输出队列
//展示
void Show(Queue *s)
{
Node *p=s->front->next;
while(p){
cout<<p->num<<" ";
p=p->next;
}
}
【7】全部代码
//队列
#include<iostream>
using namespace std;
typedef struct Node{
int num;
struct Node *next;
}Node;
//队链的q是一个结构体而不是指针结构体,故不用像链表一样设为*node,直接Queue q
typedef struct Queue{
int cnt;
struct Node *front,*rear;
}Queue;
//初始化队链
int InitQueue(Queue *q)
{
q->front=q->rear=new Node;
q->front->next=NULL;
q->cnt=0;
}
//判空
int QueueEmpty(Queue *q)
{
if(q->front==q->rear)
return 1;
else
return 0;
}
//求队列的长度
int QueueSize(Queue *q)
{
return q->cnt;
}
//进队
int Push(Queue *q,int data)
{
Node *node=new Node;
node->num=data;
node->next=NULL;
q->rear->next=node;
q->rear=node;
q->cnt++;
}
//出队
int Pop(Queue *q,int *e)
{
Node *p=q->front->next;
*e=p->num;
q->front->next=p->next;
if(p==q->rear){
q->rear=q->front;
}
delete p;
q->cnt--;
}
//展示
void Show(Queue *s)
{
Node *p=s->front->next;
while(p){
cout<<p->num<<" ";
p=p->next;
}
}
int main()
{
Queue s;
InitQueue(&s);
for(int i=0;i<6;i++)
{
Push(&s,i);
}
Show(&s);
cout<<endl;
int a;
Pop(&s,&a);
cout<<"a="<<a<<endl;
cout<<"是否为空:"<<QueueEmpty(&s)<<endl;
cout<<"队的长度:"<<QueueSize(&s)<<endl;
}
以上是全部内容,如有不对之处希望大家能在评论区指出,一起进步~