8月11日

链式队列

//头文件
#ifndef _LINKQUEUE_H
#define _LINKQUEUE_H

#include<stdio.h>
#include<stdlib.h>

#define SUCCESS 10000
#define FAILURE 10001
#define TRUE    10002
#define FALSE   10003

struct Node              
{
    int data;                 // 数据域
    struct Node *next;        // 指针域
};
typedef struct Node node;

struct Queue
{
    node *front;           // 队头指针
    node *rear;            // 队尾指针
};
typedef struct Queue Q;

int Init(Q **q);           // 初始化
int Insert(Q *q,int e);    // 向链式队列中插入节点
int Delete(Q *q);          // 删除队列节点信息
int Empty(Q *q);           // 判断队列是否为空
int Getfrist(Q *q);        // 得到队列第一个元素
int Clear(Q *q);           // 清空队列
int Destroy(Q **q);        // 销毁

#endif

#include "Queue.h"

int Init(Q **q)       // 初始化
{
    *q = (Q *)malloc(sizeof(Q)*1);
    if( (*q) == NULL)       // 判断空间是否分配成功
    {
        return FAILURE;
    }

    node *p = (node *)malloc(sizeof(node)*1);   // 申请头结点
    if(p == NULL)         // 判断空间是否分配成功
    {
        return FAILURE;
    }

    (*q)->front = (*q)->rear = p;  // front和rear都指向头节点
    p->next = NULL;  // 头节点next指向NULL
    return SUCCESS;
}

int Insert(Q *q,int e)     // 插入 数据e
{
    if(q == NULL)          // 入参判断
    {
        return FAILURE;
    }
    node *p = (node *)malloc(sizeof(node)*1);  // 为节点分配空间
    p->data = e;                               // 为节点分配数据
    q->rear->next = p;                         // rear->next 指向 节点p
    p->next = NULL;                            // p的next指向空
    q->rear = p;                               // rear 指向 p
    return SUCCESS;
}

int Delete(Q *q)               // 删除节点,删除前记录节点,释放节点空间
{
    if(q == NULL || q->front == q->rear)   // 入参判断 以及 判断队列是否为空
    {
        return FAILURE;
    }

    int e;
    node *p = q->front->next;    // 记录位置
    e = p->data;                 // 记录数据
    q->front->next = p->next;    // 尾指向下一个节点
    if(p->next == NULL)          // 判断是不是最后一个,是就把尾指针指向队头指针
    {
        q->rear = q->front;       
    }
    free(p);
    return e;
}
    
int Empty(Q *q)        // 判断是否为空
{
    if(q == NULL)      // 入参判断
    {
        return FAILURE;
    }

    return (q->front == q->rear)? TRUE : FALSE; 
}

int Getfrist(Q *q)
{
    if(q == NULL || q->front == q->rear)    // 入参判断 以及 判断队列是否为空
    {
        return FAILURE;
    }

    return q->front->next->data;    // 返回第一个元素,但是不出队
}

int Clear(Q *q)     // 就是把所有的有数据的节点删除,并把删除节点申请的空间释放掉
{
    if(q == NULL || q->front == q->rear)     // 入参判断 以及 判断队列是否为空
    {
        return FAILURE;
    }
    node *p = q->front->next;  // 先记录删除的节点
    while(p)
    {
        q->front->next = p->next;
        free(p);
        p = p->next;
    }
    q->rear = q->front;   // 清空后让队尾指针指向队头指针 ,防止队尾指针变成野指针

    return SUCCESS;
}

int Destroy(Q **q)   // 释放掉申请队列的结构体空间 和 节点的结构体的空间
{
    if(q == NULL || (*q) == NULL)  // 入参判断
    {
        return FAILURE;
    }
    free((*q)->front);             // 释放头节点
    free(*q);                      // 释放队结构体空间
    return SUCCESS;
}


#include "Queue.h"

int main()
{
    int ret,i;
    Q *p;   

    ret = Init(&p);                               //初始化
    if(ret == FAILURE)
    {
        printf("Init FAILURE!\n");
    }
    else
    {
        printf("Init SUCCESS!\n");
    }

    for(i = 0; i < 5; i++)
    {
        ret = Insert(p,i);           // 插入节点
        if(ret == FAILURE)
        {
            printf("Insert %d Failure!\n",i);
        }
        else
        {
            printf("Insert %d Success!\n",i);
        }
    }
    for(i = 0; i < 3; i++)
    {
        ret = Delete(p);                         // 删除节点
        if(ret == FAILURE)
        {
            printf("Delete Failure!\n");
        }
        else
        {
            printf("Delete %d Success!\n",ret);
        }
    }
    
    ret = Empty(p);          // 判断是否为空
    if(ret == FAILURE)
    {
        printf("Failure!\n");
    }
    else if(ret == TRUE)
    {
        printf("Queue is Empty!\n");
    }
    else
    {
        printf("Queue is not Empty!\n");
    }

    ret = Getfrist(p);                             // 获取第一个元素
    if(ret == FAILURE)
    {
        printf("Get frist Failure!\n");
    }
    else
    {
        printf("Get frist is %d \n",ret);
    }
    
    ret = Clear(p);                                // 清空队列
    if(ret == FAILURE)
    {
        printf("Clear Failure!\n");
    }
    else
    {
        printf("Clear Success!\n");
    }

    ret = Destroy(&p);                            // 销毁队列
    if(ret == SUCCESS)
    {
        printf("Destroy Success!\n");
    }
    else
    {
        printf("Destroy Failure!\n");
    }

    return 0;
}

 

阅读更多

您知道吗?(Tips Everyday)(8月11日

08-11

假设有这样的函数:rnrn输入两个字符串,一个主串,一个模式串;rn要求将主串翻转后再进行模式查找,搜索子串,返回第一个子串的位置;rnrn我们可以这样写:rn/* 以下代码未经测试,并没有处理任何异常,仅作为示范代码 */rnbool StrMyStr( const char *szSrc, const char *szDest )rnrn size_t len = strlen( szSrc );rn char *szTemp = new char[len + 1];rn memcpy( szTemp, szSrc, len + 1 );rn return (strstr( _strrev( szTemp ), szDest ) != 0 );rnrnrn但当我们去测试这段代码的性能时却发现,当处理很长的字串时rnchar *szTemp = new char[len + 1];rn这一句是相当费时的。如果这个函数被频繁调用,那么会极大的影响效率。那么有没有更好的解决方案呢?答案是有的,C++为我们提供了定位的new操作符,从语言的角度上直接支持了内存池。rnrn定位的new的语法:rn::new (地址) 类型 [长度];rnrn现在我们的程序可以这样写了:rn/* 以下代码在VC.net环境中编译、调试通过,并正常运行 */rn/* Creamdog保留所有权力 */rnrn#include rn#include rnusing namespace std;rnrnchar *g_pBuffer;rnrnbool StrMyStr( const char *szSrc, const char *szDest )rnrn size_t len = strlen( szSrc );rn char *szTemp = new (g_pBuffer) char[len + 1];rn memcpy( szTemp, szSrc, len + 1 );rn return (strstr( _strrev( szTemp ), szDest ) != 0 );rnrnrnvoid main()rnrn g_pBuffer = new char[10240];rn char a[] = "as;dflkjasdf";rn cout << StrMyStr( a, "jkl" );rn delete []g_pBuffer;rnrnrnrn经测,字符串越长效率提升越大。rnrn需要注意的几点:rn1. 不要对定位new出来的内存进行delete操作,你只需要重新new就可以了。rn2. 如果想用定位new出几块不同的内存,你需要在定位上加上上次new的内存长度的偏移,也就是这样:rnchar *szTemp1 = new (g_pBuffer) char[len];rnchar *szTemp2 = new (g_pBuffer + len) char[len];rn3. 不要忘记给内存池分配内存,更不要忘记在不用时delete[]它!

没有更多推荐了,返回首页