-
栈是先进后出的结构(弹夹)
队列是先进先出的(排队) -
栈和队列在实现结构上可以有数组和链表两种方式
-
栈结构的基本操作:
1、压栈操作
2、访问栈顶元素
3、弹栈
4、返回当前栈中的元素个数 -
队列结构的基本操作:
1、队列元素进队列是从队尾插入的
2、队列元素出队列是从对头弹出的 (类似于日常排队)
栈
/*栈的结构定义(顺序栈)*/
#define MAXSIZE 100
typedef int ElemType; /*视栈中要存放的具体元素类型而定*/
typedef int Status;
typedef struct
{
ElemType data[MAXSIZE]; //利用系统的栈来存放栈元素
int top;
}Stack;
typedef struct
{
ElemType *base; //利用堆来存放栈的元素
ElemType *top; //栈顶指针和栈底指针
int count; //栈的大小
}Stack1;
/*栈的初始化*/
Status InitStack(Stack *s)
{
if(s == NULL)
{
return -1;
}
s->top = -1; //初始化栈顶指针
return 0;
}
#define NUM 10
Status InitStack(Stack1 *s1)
{
if(s1 == NULL)
{
return -1;
}
s1->top = (ElemType *)malloc(sizeof(ElemType)*NUM); //初始化栈顶指针
if(NULL == s1->top)
{
return -1; //申请内存失败
}
s1->base = s1->top;
s1->count = 0;
return 0;
}
/*压栈*/
Status push(Stack *s, ElemType e)
{
if(s->top == MAXSIZE-1)
{
//栈满
return -1;
}
s->top++;
s->data[s->top] = e;
return 0;
}
Status push(Stack1 *s1, ElemType e)
{
if(s1->top == s1->base+NUM-1)
{
//栈满
return -1;
}
*(s1->top) = e;
s1->top++;
s1->count++;
return 0;
}
/*出栈*/
Status pop(Stack *s, ElemType *e)
{
if(s->top == -1)
{
//栈空
return -1;
}
*e = s->data[s->top];
s->top--;
return 0;
}
Status pop(Stack1*s1, ElemType *e)
{
if(s1->top == s1->base)
{
//栈空
return -1;
}
*e = *(s1->top);
s1->top--;
s->count--;
return 0;
}
/*链式栈*/
/*栈元素的(节点的结构)和栈结构的定义*/
typedef int ElemType;
typedef int Status;
/*结点的结构*/
typedef struct node
{
ElemType data;
struct node *next;
}Node;
/*栈的结构*/
typedef struct
{
struct node *top; //栈顶指针
int count; //用来记录栈元素的个数
}Stack;
/*链栈初始化*/
Status InitStack(Stack *s)
{
if(NULL == s)
{
return -1;
}
s->top = NULL; //栈空,栈顶指针指向NULL
s->count = 0;
return 0;
}
/*把链表的头指针当作栈的栈顶指针,链表的尾结点当作栈底*/
/*栈元素只在栈顶进栈或者出栈*/
/*压栈*/
Status push(Stack *s, ElemType e)
{
if(NULL == s)
{
return -1;
}
Node *p = (Node *)malloc(sizeof(Node)); //申请一个节点
if(NULL == p)
{
return -1;
}
p->data = e;
p->next = s->top; //令新创建的节点指向当前的栈顶
s->top = p; //栈顶指针指向新压栈的元素
s->count++;
return 0;
}
/*出栈*/
Status pop(Stack *s, ElemType *e)
{
if(NULL==s || NULL==s->top)
{
return -1;
}
*e = s->top->data; //取出栈顶元素的值
Node *temp = s->top; //保存当前要出栈的栈顶元素的地址
s->top = s->top->next; //将栈顶指针移向下一个元素
s->count--;
free(temp); //释放当前栈顶元素的指针
return 0;
}
队列
/*循环队列(顺序结构)*/
#define MAXSIZE 10 //队列的大小
typedef int ElemType;
typedef int Status;
/*顺序队列结构*/
typedef struct
{
ElemType data[MAXSIZE]; //利用系统的栈来存放队列的元素
int front; //队头(出队)
int rear; //队尾(进队)
}Queue;
/*队列的初始化*/
Status InitQueue(Queue *q)
{
if(NULL == q)
{
return -1;
}
q->rear = 0;
q->front = 0;
return 1;
}
/*返回循环队列的元素个数*/
int NumQueue(Queue *q)
{
return (q->rear-q->front+MAXSIZE)%MAXSIZE;
}
/*进队列(从队尾进队)*/
Status EnQueue(Queue *q, ElemType e)
{
if(NULL==q || (q->rear+1)%MAXSIZE==q->front)
{
return -1;
}
q->data[q->rear] = e;
q->rear = (q->rear+1) % MAXSIZE;
return 0;
}
/*出队列(从队头出队)*/
Status OutQueue(Queue *q, ElemType *e)
{
if(q==NULL || q->rear==q->front)
{
return -1;
}
*e = q->data[q->front];
q->front = (q->front+1) % MAXSIZE;
return 0;
}
/*用链表实现队列*/
/*队列元素的结点结构和队列结构*/
/*队列存储的元素的类型*/
typedef int ElemType;
typedef int Status;
/*结点结构*/
typedef struct node
{
ElemType data;
struct node *next;
}Node;
/*队列结构(一个队头指针,一个队尾指针)*/
typedef struct
{
struct node *front;
struct node *rear;
}Queue;
/*链式队列的初始化*/
/*无头结点*/
Status InitQueue(Queue *q)
{
if(NULL == q)
{
return -1;
}
q->front = NULL;
q->rear = NULL;
return 0;
}
/*有头结点*/
Status InitQueue(Queue *q)
{
if(NULL == q)
{
return -1;
}
/*创建一个头结点*/
Node *p = (Node *)malloc(sizeof(Node));
if(NULL == p)
{
return -1;
}
/*初始化头结点和队头队尾指针*/
p->next = NULL;
q->front = p;
q->rear = p;
return 0;
}
/*元素进队列*/
Status EnQueue(Queue *q, ElemType e)
{
if(NULLL == q)
{
return -1;
}
Node *temp = (Node *)malloc(sizeof(Node));
if(NULL == temp)
{
//申请内存失败
return -1;
}
/*初始化新插入的节点*/
temp->next = NULL;
temp->data = e;
/*从队尾连接新插入的节点并把队尾指针指向新插入的节点*/
q->rear->next = temp;
q->rear = temp;
return 0;
}
/*元素出队列*/
/*无头结点版本,从队头出队*/
Statu OutQueue(Queue *q, ElemType *e)
{
if(NULL == q || (NULL==q->rear))
{
return -1;
}
if(q->front == q->rear)
{
/*如果大家都指向同一个节点证明队列只有一个元素,那么q->rear也应该要改变*/
free(q->front);
q->front = NULL;
q->rear = NULL;
return 0;
}
Node *temp = q->front;
*e = q->front->data;
q->front = q->front->next;
free(temp);
return 0;
}
/*有头结点版本*/
Status OutQueue(Queue *q, ElemType *e)
{
if(NULL==q || (q->rear==q->front))
{
return -1;
}
Node *temp = q->front->next;
if(q->front->next == q->rear)
{
q->rear = q->front;
}
q->front->next = temp->next;
*e = temp->data;
free(temp);
return 0;
}
/*计算队列元素的数量*/
/*无头结点*/
int NumQueue(Queue *q)
{
if(NULL == q)
{
return -1;
}
int count = 1;
Node *temp1 = q->front;
Node *temp2 = q->rear;
if(temp1==NULL && temp2==NULL)
{
return 0;
}
else if(temp1 == temp2)
{
return count;
}
while(temp1 != temp2)
{
count++;
temp1 = temp1->next;;
}
return count;
}
附:练习题
循环队列的应用——舞伴配对问题:在舞会上,男、女各自排成一队。舞会开始时,依次从男队和女队的队头各出一人配成舞伴。如果两队初始人数不等,则较长的那一队中未配对者等待下一轮舞曲。假设初始男、女人数及性别已经固定,舞会的轮数从键盘输入。试模拟解决上述舞伴配对问题。要求:从屏幕输出每一轮舞伴配对名单,如果在该轮有未配对的,能够从屏幕显示下一轮第一个出场的未配对者的姓名。
//舞伴配对问题
#define MAXSIZE 10
typedef struct
{
int *base;
int front,rear;
}Man;
typedef struct
{
char *base;
int front,rear;
}Woman;
void ManQueue(Man &Q,int m)//建立一个男人队列
{
Q.base =(int *)malloc(sizeof(int)*MAXSIZE);
if(!Q.base )return;
Q.front =Q.rear =0;
for(int i=0;i<m;i++)
{
printf("输入第%d个男人名:",i+1);
scanf("%d",&Q.base[Q.rear]);
Q.rear =(Q.rear +1)% MAXSIZE;
}
printf("输出男人队列:");
for(i=0;i<m;i++)
printf("%d ",Q.base[i]);
printf("\n");
}
void WomanQueue(Woman &Q,int n)//建立一个女人队列
{
Q.base =(char *)malloc(sizeof(char)*MAXSIZE);
if(!Q.base )return;
Q.front =Q.rear =0;
getchar();
for(int i=0;i<n;i++)
{
printf("输入第%d个女人名:",i+1);
scanf("%c",&Q.base[Q.rear]);
Q.rear =(Q.rear +1)% MAXSIZE;
getchar();
}
printf("输出女人队列:");
for(i=0;i<n;i++)
printf("%c ",Q.base[i]);
printf("\n");
}
void peidui(Man Q1,Woman Q2,int m,int n,int k)//配对——k表示第几轮
{
int min,Mname;
char Wname;
if(m>n) min=n;else min=m;
for(int i=1;i<=k;i++)//第几轮
{
for(int j=0;j<min;j++)
{
Mname=Q1.base[Q1.front];
Wname=Q2.base[Q2.front];
Q1.front=(Q1.front+1)%MAXSIZE;
Q2.front=(Q2.front+1)%MAXSIZE;
printf("配对者:%d--%c\n",Mname,Wname);
Q1.base [Q1.rear] =Mname;
Q1.rear =(Q1.rear +1)%MAXSIZE;
Q2.base [Q2.rear] =Wname;
Q2.rear =(Q2.rear +1)%MAXSIZE;
}
if(m>n)//男人多
{
printf("未配对的第一个出来的是:%d\n",Q1.base[Q1.front]);
}
else//女人多
{
printf("未配对的第一个出来的是:%c\n",Q2.base[Q2.front]);
}
}
}
void main()
{
Man Q1;
Woman Q2;
ManQueue(Q1,4);
WomanQueue(Q2,6);
peidui(Q1,Q2,4,6,3);
}