10.数据结构学习4.0

10.数据结构学习4.0

1、队列的顺序存储

1、定义:分配一块连续的存储单元存放队列中的元素,并附设两个指针:队头指针front指向对头元素,队尾指针rear指向队尾元素的下一个位置;

#define MaxSize 50  //定义队列中元素的个数
typedef struct{
    ElementType data[MxSize];//存放队列元素
    int front,rear;//队头指针,队尾指针
}SqQueue;

2、循环队列:将顺序队列臆造成一个环状的空间,即把存储队列元素的表从逻辑上视为一个环,称为循环队列。

struct Queue
{
    ElementType data[Max];
    int front,rear;
    //int len;//记录数组长度
    //ElementType FrontData;//记录出队的元素
    //int flag;设置标志位记录当前是否插入了元素
};

3、循环队列的初始化:

int InitQueue(struct Queue *q)
{
    q->front = 0;
    q->rear = 0;
}

4、判断队满还是队空的三种处理方法

【1】、牺牲一个单元来区分队空和队满,入对时少用一个队列单元,约定以对头指针在队尾指针的下一位置作为队满的标志;

队满条件:(Q.rear+1)%MaxSize == Q.front

队空条件:Q.rear == Q.front

队列中元素的个数:(Q.rear-Q.front+MaxSize)%MaxSize

//判断队空
bool IsEmpty(SqQueue Q)
{
    if(Q.rear == Q.front)
    {
        return true
    }
    else
    {
        return false;
    }
}

【2】、类型中增设元素个数的数据成员len。这样队空的条件为Q.len==0;队满的条件为Q.len == MaxSize

【3】、类型中增设 flag 数据成员,以区分是队满还是队空。flag == 0时,若因删除导致Q.front == Q.rear,则队空;flag == 1的时候,若因插入导致Q.front == Q.rear ,则队满。

5、入队

void Push(struct Queue *q,ElementType element)
{
    if(Q.rear+1)%MaxSize == Q.front)
    {
        printf("The queue is full!\n");
        return ;
    }
    q->data[q->rear] = element;
    q->rear++;
    q->rear = q->rear%MaxSize;
    q->len++;
}

6、出队

ElementType* Pop(struct Queue *q)
{
    if(q->rear == q->front)
    {
        printf("The queue is empty!\n");
        return ;
    }
    q->FrontData = q->data[q->front];
    q->len--;
    q->front++;
    q->front = q->front%Max;
    return &q->FrontData;
}
2、栈和队列的相互转换
  • 两个栈实现一个队列
#include<stdio.h>
#include"LinkStack.h"//自己封装的栈头文件,在数据结构学习3.0中有相关代码
#define true 1
#define false 0

struct Queue
{
    LStack inputStack;//初始化两个栈用来模拟入队、出队
    LStack outputStack;
};
//对队列的初始化就是对两个栈分别进行初始化
int InitQueue(struct Queue *q)
{
    Init
        tack(&q->inputStack);
    InitStack(&q->outputStack);
    return true;
}
//判断队列是否为空
int IsStackQueueEmpty(struct Queue *q)
{
    if(IsEmpty(&q->inputStack) == true && IsEmpty(&q->outputStack) == true)
    {
        return true;
    }
    else
    {
        return false;
    }
}
//入队列,判断哪个队列有数据将当前元素压入栈
void StackQueuePush(struct Queue *q,ElementType element)
{
    while(IsEmpte(&q->outPutStack) == false)
    {
        Push(&q->inputStack,*Pop(&q->outputStack));
    }
    Push(&q->inputStack,element);
}
//出队列,将一个有数据的栈里n个数据转移到另一个栈中,然后弹出栈顶元素
ElementType* StackQueuePop(struct Queue *q)
{
    if(IsStackQueueEmpty(q) == true)//判断当前模拟队列是否为空,即为两个栈是否为空
    {
        printf("Queue is Empty!\n");
        return NULL;
	}
    while(IsEmpty(&q->inputStack) == false)
    {
        Push(&q->outputStack,*Pop(&q->inputStack));
	}
    return Pop(&q->outputStack);
}
int main()
{
    struct Queue queue;
    InitQueue(&queue);
    for(int i=0;i<10;i++)
    {
        StackQueuePush(&queue,i+1);//模拟入栈
    }
    while(IsStackQueueEmpty(&queue) == false)
    {
        printf("%d ",*StackQueuePop(&queue));//模拟出栈
	}
    return 0;
}
//输出结果1 2 3 4 5 6 7 8 9 10
  • 两个队列实现一个栈

算法思想:因为队列的操作是先进先出,所以对于队列来说,实现模拟栈的出栈操作,需要设置两个队列,如果当前队列中有数据,即将当前队列中的前n-1个数据转移到另一个队列中,然后输出剩余的最后一个元素。模拟栈的入栈操作,只需要将所在的元素入队即可。

#include<stdio.h>
#include"Queue.h"//自己封装的队列头文件,在数据结构学习3.0中有相关代码
#define true 1
#define false 0
//定义一个栈的结构体,用两个队列进行模拟
struct Stack
{
    LQueue queue1;
    LQueue queue2;
};
//初始化一个栈,分别对两个队列进行初始化
int InitQueueStack(struct Stack *s)
{
    InitLQueue(&s->queue1);
    InitLQueue(&s->queue2);
    return true;
}
//判断队列是否为空
int IsQueueStackEmpty(struct Stack *s)
{
    if(s->queue1.queue.len == 0&& s->queue2.queue.len == 0)
    {
        return true;
    }
    else
    {
        return false;
	}
}
//模拟入队,哪个栈中有元素将那个元素入栈
void QueueStackPush(struct Stack *s,ElementType element)
{
    if(IsQEmpty(s->queue1) == true)
    {
        QPush(&s->queue2,element);
    }
    else
    {
        QPush(&s->queue1,element);
    }
}
//模拟出队,哪个栈中有元素将该栈中的前n-1个转移到另一个栈中,然后弹出栈顶元素
ElementType* QueueStackPop(struct Stack *s)
{
    if(IsQEmpty(&s->queue1) == true)
    {
        while(s->queue2.queue.len>1)
        {
            QPush(&s->queue1,*QPop(&s->queue2));
		}
        return QPop(&s->queue2);
	}
    if(IsQEmpty(&s->queue2) == true)
    {
        while(s->queue1.queue.len>1)
        {
            QPush(&s->queue2,*QPop(&s->queue1));
		}
        return QPop(&s->queue1);
	}
}
int main()
{
    struct Stack s;
    InitQueueStack(&s);
    for(int i=0;i<10;i++)
    {
        QueueStackPush(&s,i+1);
    }
    while(IsQueueStackEmpty(&s) == false)
    {
        printf("%d ",*QueueStackPop(&s));
    }
    printf("\n");
    return 0;
}
//输出结果10 9 8 7 6 5 4 3 2 1
3、栈和队列的实际应用

问题描述:设停车场只有一个可停放几辆汽车的狭长通道,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达的先后依次排序,若停车场内已经停满几辆汽车,则后来的汽车只能在门外的便道上等候,一旦停车场内有车开走,则排在便道上的第一辆车即可进入;当停车场内某辆车要离开的时候,由于停车场是狭长的通道,在它之后开入的车辆必须先退出车场为它让路,待该辆车开出大门后,为它让路的车辆再按原次序进入车场。在这里假设汽车不能从便道上开走。

基本要求:

以栈模拟停车场,以队列模拟车场外的便道,按照从终端输入数据序列进行模拟管理,每一组输入数据包括三个数据项:汽车”到达“或”离去“信息、汽车牌照号码以及达到或离去的时刻。对每一组输入数据进行操作后的输出信息为:若是车辆到达,则输出车辆在停车场或便道上的停车位置;若是车辆离去,则输出车辆在停车场内停留的时间和应该缴纳的费用(在便道上停留的时间不收费)。

#include<stdio.h>
#include<stdlib.h>
#include"LinkStack.h"//自定义的链栈
#include"Queue.h"//自定义的队列
#include"MyString.h"
#define Max_Size 3  //定义停车场最大容量
#define true 1
#define false 0
struct Car
{
    MyString name;//记录车牌号
    double arriveTime;//记录到达时间
    double leaveTime;//记录离开时间
};
struct Car* CreateCar(const char *name,double arriveTime)
{
    //申请一个车的结构体对象
    struct Car* newCar = (struct Car*)malloc(sizeof(struct Car));
    if(newCar == NULL)
    {
        printf("Create malloc error!\n");
        return NULL;
	}
    Initialize(&newCar->name,name);//对车牌号用MyString字符串的初始化函数进行初始化
    newCar->arriveTime = arriveTime;
    return newCar;
}
void FreeCar(struct Car* car)
{
    if(car == NULL)//判断要操作的对象是否为空
    {
        return ;
    }
    FreeMyString(&car->name);//释放车牌号,因为车牌号是在堆上申请的字符串类型,所以用自定义的字符串释放函数
    free(car);//释放小车
}
void Come_car(LStack *CarStop,LQueue *pavement)
{
    char CarName[100] = {0};
    double arriveTime =0.0;
    printf("请输入车牌号: ");
    scanf("%s",CarName);
    printf("请输入到达的时间: ");
    scanf("%lf",&arriveTime);
    struct Car* newCar = CreateCar(CarName,arriveTime);
    if(newCar == NULL)
    {
        printf("没有车达到!\n");
        return;
    }
    if(CarStop->stack.len < Max_Size)//判断当前停车场是否还有空位
    {
        Push(CarStop,newCar);//将车压入栈中
        printf("当前停车场未满,车辆 |%s| 停在停车场第 %d 号车位!\n",newCar->name.String,CarStop->stack.len);
    }
    else//没有位置则将车子停入便道
    {
        QPush(pavement,newCar);
        printf("当前停车场已满,车辆 |%s| 停在了便道的第 %d 号车位!\n",newCar->name.String,pavement->queue.len);
    }
}
//车辆离开
void Leave_car(LStack *CarStop,LQueue *pavement)
{
    char CarName[100] = {0};
    printf("请输入要离开的车牌号: ");
    scanf("%s",CarName);
    Init_MyString(LeaveCarName,CarName);//初始化车辆名字

    LStack TempStack;//申请一个临时栈用来存放开出去的车
    InitLStack(&TempStack);//初始化临时栈
    double LeaveCarTime = 0.0;//记录离开时间
    while(IsEmpty(CarStop) == false)//当停车场有车的时候
    {
        //申请一个变量记录弹出的车辆
        struct Car *car=(struct Car*)*Pop(CarStop);
        if(car->name.isEqual(&car->name,&LeaveCarName) == true)//判断当前车牌号和要离开的车牌号是否相同
        {
            printf("请输入汽车要离开的时间: ");
            scanf("%lf",&car->leaveTime);//键入离开时间
            LeaveCarTime = car->leaveTime;
            printf("\n");
            printf("车辆|%s|将要离场,到达时间是%lf,离开时间是%lf,停车费用为%lf\n",car->name.string,car->arriveTime,car->leaveTime,(car->leaveTime-car->arriveTime)*5);
            FreeCar(car);//释放小车变量
            break;
        }
        Push(&TempStack,car);//和要找的车牌号不相同,则将车压入临时栈
    }
    while(IsEmpty(&TempStack) == false)//将进入临时栈的小车重新返回
    {
        Push(CarStop,*Pop(&TempStack));//将临时栈中的元素重新返回停车场
    }
    if(CarStop->stack.len<Max_Size)//当停车场有空位将便道上的车压入停车场
    {
        if(IsQEmpty(pavement) == false)//判断便道上是否有车
        {
            //设置一个临时变量用来记录从便道队列中弹出的元素
            struct Car *car=(struct Car*)*QPop(pavement);
            car->arriveTime = LeaveCarTime;
            Push(CarStop,car);//将小车压入停车场栈中
            printf("便道上的车|%s|进入了停车场,时间为%lf\n",car->name.string,car->arriveTime);
        }
    }
    else
    {
        printf("未找到输入的车牌!\n");
    }
}
//显示停车场中车辆信息
void DisplayCarStop(LStack *carStop)
{
    printf("----------------------------------------------------\n");
    Node *TravelPoint = carStop->stack.head;
    while(TravelPoint != NULL)
    {
        struct Car *car=(struct Car*)TravelPoint->data;
        printf("车牌:|%s| 到达时间:%lf\n",car->name.string,car->arriveTime);
        TravelPoint = TravelPoint->next;
    }
    printf("\n");
    printf("----------------------------------------------------\n");
}
//显示便道中车辆信息
void DispalyPavement(LQueue *pavement)
{
    printf("----------------------------------------------------\n");
    Node *TravelPoint = pavement->queue.head;
    while(TravelPoint != NULL)
    {
        struct Car *car=(struct Car*)TravelPoint->data;
        printf("车牌:|%s| 到达时间:%lf\n ",car->name.string,car->arriveTime);
        TravelPoint = TravelPoint->next;
    }
    printf("\n");
    printf("----------------------------------------------------\n");
}
int main()
{
    LStack carStop;
    InitLStack(&carStop);

    LQueue pavement;
    InitLQueue(&pavement);

    int choice=0;
    while(1)
    {
        printf("~~~~~~~~~~~~~~~~carStop~~~~~~~~~~~~~~~~\n");
        printf("1、车辆进入停车厂\n");
        printf("2、车辆离开停车厂\n");
        printf("3、显示停车场信息\n");
        printf("4、显示便道信息\n");
        printf("5、退出系统\n");
        printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
        scanf("%d",&choice);
        switch (choice)
        {
        case 1:
            Come_Car(&carStop,&pavement);
            break;
        case 2:
            Leave_car(&carStop,&pavement);
            break;
        case 3:
            DisplayCarStop(&carStop);
            break;
        case 4:
            DispalyPavement(&pavement);
            break;
        case 5:
            Node *TravelPoint = pavement.queue.head;
            while(TravelPoint != NULL)
            {
                struct Car *car=(struct Car*)TravelPoint->data;
                FreeCar(car);
                TravelPoint = TravelPoint->next;
            }
            FreeQueue(&pavement);

            TravelPoint = carStop.stack.head;
            while(TravelPoint != NULL)
            {
                struct Car *car=(struct Car*)TravelPoint->data;
                FreeCar(car);
                TravelPoint = TravelPoint->next;
            }
            FreeStack(&carStop);
            return 0;
        default:
            break;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值