队列--链队列

425 阅读3分钟

上一篇文章中我们说到了循环队列,今天我们来说一说如何用链式结构来存储队列。

链队列

是不是感觉很熟悉,这分明就是单向链式表嘛。front指向队头,rear指向队尾,没毛病。 入队时,队尾追加新节点temp,rear指向新结点temp,新节点temp成队尾; 出队时,用一个临时结点delTemp暂存front指向结点,front指向delTemp的下一个结点,临时结点delTemp释放,也就是从当前队列中出队了。

注意:一定是要先把front指向一下一个结点,然后在释放,否则front可能就找不到下一个结点了呢。

来,闲话不多说,翠花,上酸菜……(代码来一波)

/* 定义链式队列*/
typedef struct QNode // 结点
{
    ElementType data;
   struct QNode *next;
   
}QNode;

// 链队列结构
typedef struct {
    QNode *front; // 队头
    QNode *rear;  // 队尾
    
}linkQueue;


// 创建一个空队列
Status createLinkQueue(linkQueue *Q){
    
    // 头指针,尾指针生成新节点
    Q->front = Q->rear = malloc(sizeof(QNode));
    
    // 判断创建结点是否成功
    if (!Q->front) {
        return ERROR;
    }
    
    return OK;
}

// 销毁队列,将队列的每个结点都释放,整个队列都没有了
Status destoryLinkQueue(linkQueue *Q){
    // 遍历队列,释放每个结点
    while (Q->front) {
        // 用rear指向front的下一个指针
        Q->rear = Q->front->next;
        
        // 释放front指针
        free(Q->front);
        
        Q->front = Q->rear;
    }
    
    return OK;
}

// 清空队列,队列还是存在的,只是队列里面的内容清空了
Status clearLinkQueue(linkQueue *Q){
    
    // 定义临时变量记录队头的位置
    QNode *head = Q->front->next;
    QNode *temp;
    
    // 头结点是一个空结点
    Q->rear = Q->front = NULL;
    
    while (head) {
        temp = head;
        head = head->next;
        free(temp);
    }
    
    
    return OK;
}

// 判断队列是否为空
Status isEmptyLinkQueue(linkQueue Q)
{
    if (Q.front == Q.rear) {
        return TRUE;
    }
    return FALSE;
}

// 判断队列的长度
int linkQueueLength(linkQueue Q){
    // 因为有一个头结点,所以从0开始计算
    int i = 0;
    
    // 临时变量记录头结点
    QNode *temp = Q.front;
    while (Q.rear != temp) {
        i ++;
        temp = temp->next;
    }
    
    return i;
}

// 入队
Status inLinkQueue(linkQueue *Q, ElementType data)
{
    //1. 创建一个新节点,数据为data
    QNode *temp = (QNode *)malloc(sizeof(QNode));
    
    // 创建不成功,返回ERROR
    if (!temp) {
        return ERROR;
    }
    
    temp->data = data;
    temp->next = NULL;
    
    // 将temp插入到队尾位置
    Q->rear->next = temp;
    
    // 移动rear指针指向最新结点
    Q->rear = temp;
    
    return OK;
}

// 出队
Status outLinkQueue(linkQueue *Q,ElementType *outData)
{
    // 如果是空队列,返回error
    if (isEmptyLinkQueue(*Q)) {
        return ERROR;
    }
    
    // 记录出队的数据
    QNode *delTemp = Q->front->next;
    *outData = delTemp->data;
    
    // 向后移动front指针
    Q->front->next = delTemp->next;
    
    // 删除的元素就是队尾元素,最后队列为空
    if (Q->rear == delTemp) {
        Q->rear = Q->front;
    }
    
    // 释放要删除的指针
    free(delTemp);
    return OK;
}

// 获取队头元素
Status getHead(linkQueue Q, ElementType *data){
    
    if (isEmptyLinkQueue(Q)) {
        return ERROR;
    }
    
    QNode *head = Q.front->next;
    *data= head->data;
    return OK;
}

Status printLinkQueue(linkQueue Q){
    if (isEmptyLinkQueue(Q)) {
        return ERROR;
    }
    
    QNode *head = Q.front->next;
    
    while (head) {
        printf("%d ",head->data);
        head = head->next;
    }
    
    printf("\n");
    
    return OK;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    printf("链队列表示与操作实现\n");
    
    linkQueue Q;

    // 创建队列
    if (createLinkQueue(&Q)) {
        printf("成功构建了一个空队列\n\n");
    }
    
    printf("是否为空队列? %d (1:是 0:否)\n\n",isEmptyLinkQueue(Q));

    
     //5.插入元素到队列中
    inLinkQueue(&Q, -3);
    inLinkQueue(&Q, 6);
    inLinkQueue(&Q, 12);
    
    printf("队列的长度为 %d\n\n",linkQueueLength(Q));
    printf("是否为空队列? %d (1:是 0:否)\n\n",isEmptyLinkQueue(Q));
       
    //6.遍历队列
    printf("队列中的元素如下:\n");
    
    // 打印队列
    printLinkQueue(Q);

    // 获取队头元素
    ElementType headData;
    if (getHead(Q, &headData)) {
        printf("队头元素:%d\n",headData);
    };

    
    // 出队
    ElementType outData;
    if (outLinkQueue(&Q, &outData)) {
        printf("出队元素 %d\n\n",outData);
    }
    
    if (getHead(Q, &headData)) {
        printf("新的队头元素:%d\n",headData);
    };
    
    //10.清空队列
    clearLinkQueue(&Q);
    
    //11.销毁队列
    destoryLinkQueue(&Q);
    
    return 0;
}

运行结果如下