王道数据结构源码实战ch3栈和队列
顺序栈
顺序栈的结构体定义
typedef struct
{
ElemType data[MaxSize]; //存放数据的连续空间
int top; //栈顶指针,指向栈顶元素
} SqStack;
初始化栈s
void Init_Stack(SqStack &s) //初始化,要改变S的内部的top,所以要引用
{
s.top=-1; //栈顶指针指向栈顶元素,初始没有,指向-1
}
判顺序栈s为空
bool Stack_Empty(SqStack s) //判空,判断栈顶指针是否为-1
{
if(s.top==-1)
return true;
else
return false;
}
入栈
bool Push_Stack(SqStack &s,ElemType x) //入栈
{
if(s.top==MaxSize-1) //栈满,元素从0开始
return false;
s.data[++s.top]=x; //先动指针,再入栈
}
获取栈顶元素
bool Get_Top(SqStack s,ElemType &e) //只获取栈顶元素,不出栈
{
if(Stack_Empty(s))
return false;
e=s.data[s.top]; //也可以省去第二个参数,e设为全局变量
return true;
}
出栈
bool Pop_Stack(SqStack &s,ElemType &e) //出栈,栈顶元素要删除
{
if(Stack_Empty(s))
return false;
e=s.data[s.top--]; //等价于x=s.data[s.top];top--;先出栈,再动指针
}
完整代码
#include<bits/stdc++.h>
using namespace std;
#define MaxSize 50
typedef int ElemType;
typedef struct
{
ElemType data[MaxSize]; //存放数据的连续空间
int top; //栈顶指针,指向栈顶元素
} SqStack;
void Init_Stack(SqStack &s) //初始化,要改变S的内部的top,所以要引用
{
s.top=-1; //栈顶指针指向栈顶元素,初始没有,指向-1
}
bool Stack_Empty(SqStack s) //判空,判断栈顶指针是否为-1
{
if(s.top==-1)
return true;
else
return false;
}
bool Push_Stack(SqStack &s,ElemType x) //入栈
{
if(s.top==MaxSize-1) //栈满,元素从0开始
return false;
s.data[++s.top]=x; //先动指针,再入栈
}
bool Get_Top(SqStack s,ElemType &e) //只获取栈顶元素,不出栈
{
if(Stack_Empty(s))
return false;
e=s.data[s.top]; //也可以省去第二个参数,e设为全局变量
return true;
}
bool Pop_Stack(SqStack &s,ElemType &e) //出栈,栈顶元素要删除
{
if(Stack_Empty(s))
return false;
e=s.data[s.top--]; //等价于x=s.data[s.top];top--;先出栈,再动指针
}
int main()
{
SqStack S;
bool flag; //栈空标志
ElemType e; //存放拿出的元素
Init_Stack(S); //初始化
flag=Stack_Empty(S);
if(flag)
cout<<"stack S is empty"<<endl;
else
cout<<"stack S isn't empty"<<endl;
Push_Stack(S,3);
Push_Stack(S,4);
Push_Stack(S,5);
Get_Top(S,e); //获取栈顶元素
cout<<e<<endl;
Pop_Stack(S,e); //出栈
Get_Top(S,e); //获取栈顶元素
cout<<e;
return 0;
}
链栈
实现方法:链表通过头插法插入,并从头部删除元素。
循环队列
循环队列结构体定义
typedef struct
{
ElemType data[MaxSize]; //存放数据的连续空间
int front; //队头指针 ,指向第一个元素
int rear; //队尾指针 ,指向最后一个元素的后面
} SqQueue;
初始化循环队列Q
void InitQueue(SqQueue &Q)
{
Q.front=Q.rear=0; //初始化为头尾指针相等都指向下标为0的元素
}
判空
bool isEmpty(SqQueue Q)
{
if(Q.front==Q.rear)
return true;
else
return false;
}
判满
bool isFull(SqQueue Q)
{
if(Q.front==(Q.rear+1)%MaxSize)
return true;
else
return false;
}
入队
队尾指针指向原本队尾元素的后面空格,所以先入队,再后移指针(与出队一致)
bool EnQueue(SqQueue &Q,ElemType x)
{
if(isFull(Q))
return false;
Q.data[Q.rear]=x; //先放入元素,队尾指针再后移
Q.rear=(Q.rear+1)%MaxSize;
return true;
}
出队
队头指针 指向原本的第一个元素,所以先出队,在把头指针后移(与入队一致)
bool DeQueue(SqQueue &Q,ElemType x)
{
if(isEmpty(Q))
return false;
x=Q.data[Q.front];
Q.front= (Q.front+1)%MaxSize; //先取出元素,头指针再后移,和入队的操作顺序是一样的
return true;
}
完整代码
#include<bits/stdc++.h>
using namespace std;
//循环队列
#define MaxSize 5
typedef int ElemType;
typedef struct
{
ElemType data[MaxSize]; //存放数据的连续空间
int front; //队头指针 ,指向第一个元素
int rear; //队尾指针 ,指向最后一个元素的后面
} SqQueue;
void InitQueue(SqQueue &Q)
{
Q.front=Q.rear=0; //初始化为头尾指针相等都指向下标为0的元素
}
bool isEmpty(SqQueue Q)
{
if(Q.front==Q.rear)
return true;
else
return false;
}
bool isFull(SqQueue Q)
{
if(Q.front==(Q.rear+1)%MaxSize)
return true;
else
return false;
}
bool EnQueue(SqQueue &Q,ElemType x)
{
if(isFull(Q))
return false;
Q.data[Q.rear]=x; //先放入元素,队尾指针再后移
Q.rear=(Q.rear+1)%MaxSize;
return true;
}
bool DeQueue(SqQueue &Q,ElemType x)
{
if(isEmpty(Q))
return false;
x=Q.data[Q.front];
Q.front= (Q.front+1)%MaxSize; //先取出元素,头指针再后移,和入队的操作顺序是一样的
return true;
}
int main()
{
SqQueue Q;
bool ret;//存储入队出队成功失败的标志;
ElemType x;//存储出队元素
InitQueue(Q); //初始化
EnQueue(Q,5);
EnQueue(Q,6);
EnQueue(Q,7); //入队测试
ret= EnQueue(Q,8);
if(ret)
cout<<"Enqueue success"<<endl;
else
cout<<"Enqueue fail"<<endl;
ret= EnQueue(Q,9); //在队满时入队失败
if(ret)
cout<<"Enqueue success"<<endl;
else
cout<<"Enqueue fail"<<endl;
//打印队列内元素
for(int i=Q.front; i<Q.rear; i++)
cout<<Q.data[i]<<endl;
//出队测试
DeQueue(Q,x);
DeQueue(Q,x);
DeQueue(Q,x);
DeQueue(Q,x);
ret= DeQueue(Q,x);
if(ret)
cout<<"Dequeue success";
else
cout<<"Dequeue fail";
return 0;
}
链队
实现方法:同时带头结点,且有头指针和尾指针的链表,从尾部插入,头部删除
结构体定义
单个结点定义
typedef struct LNode //定义节点
{
ElemType data;
struct LNode *next;
} LNode,*LinkList;
链队结构体定义
typedef struct //定义内没有指向自身的指针,所以此处可以省略
{
LNode *front,*rear; //队列由指向节点类型的 头指针与为尾指针组成
}LinkQueue; //只需要指针,和链表一样,定义一个链表也只需要一个指针
初始化链队
void InitQueue(LinkQueue &Q) //有头结点
{
Q.front=Q.rear=(LNode*)malloc(sizeof(LNode)); //生成一个头结点,队首和队尾指针都指向它
Q.front->next=NULL;
}
入队(尾插法)
void EnQueue(LinkQueue &Q,ElemType x) //入队,尾插法
{
LNode* s=(LNode*)malloc(sizeof(LNode));//待插入节点
s->data=x;
s->next=NULL; //挂右(尾插右边是空)
Q.rear->next=s; //挂左边
Q.rear=s; //更新rear,尾指针后移
}
出队(从头部删除)
bool DeQueue(LinkQueue &Q,ElemType x) //出队,头部删除,
{
if(Q.front==Q.rear) //判空
return false;
LNode *p=Q.front->next; //相当于单链表删除第一个元素,前驱就是头结点,所以单链表找前驱这一步省略了
x=p->data;
Q.front->next=p->next;
if(Q.rear==p) //!!!特别注意之处,删除时仅剩一个元素,还要改变尾指针,将队列置空
Q.rear=Q.front;
free(p);
return true;
}
完整代码
#include<bits/stdc++.h>
using namespace std;
typedef int ElemType;
typedef struct LNode //定义节点
{
ElemType data;
struct LNode *next;
} LNode,*LinkList;
typedef struct //定义内没有指向自身的指针,所以此处可以省略
{
LNode *front,*rear; //队列由指向节点类型的 头指针与为尾指针组成
}LinkQueue; //只需要指针,和链表一样,定义一个链表也只需要一个指针
void InitQueue(LinkQueue &Q) //有头结点
{
Q.front=Q.rear=(LNode*)malloc(sizeof(LNode)); //生成一个头结点,队首和队尾指针都指向它
Q.front->next=NULL;
}
void EnQueue(LinkQueue &Q,ElemType x) //入队,尾插法
{
LNode* s=(LNode*)malloc(sizeof(LNode));//待插入节点
s->data=x;
s->next=NULL; //挂右(尾插右边是空)
Q.rear->next=s; //挂左边
Q.rear=s; //更新rear,尾指针后移
}
bool DeQueue(LinkQueue &Q,ElemType &x) //出队,头部删除,
{
if(Q.front==Q.rear) //判空
return false;
LNode *p;
p=Q.front->next; //相当于单链表删除第一个元素,前驱就是头结点,所以单链表找前驱这一步省略了
x=p->data;
Q.front->next=p->next;
if(Q.rear==p) //!!!特别注意之处,删除时仅剩一个元素,还要改变尾指针,将队列置空
Q.rear=Q.front;
free(p);
return true;
}
void ShowList1(LinkList L)
{
L=L->next;
while(L)
{
cout<<L->data<<" ";
L=L->next;
}
cout<<endl;
}
int main()
{
LinkQueue Q;
ElemType x;
InitQueue(Q);
EnQueue(Q,5);
EnQueue(Q, 6);
EnQueue(Q, 7);
ShowList1(Q.front);
DeQueue(Q,x);
cout<<x<<endl;
ShowList1(Q.front);
return 0;
}