栈和队列初识(一)

  • 栈是先进后出的结构(弹夹)
    队列是先进先出的(排队)

  • 栈和队列在实现结构上可以有数组和链表两种方式

  • 栈结构的基本操作:
    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);     
 }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值