链表-可pop任意字节的队列-续

链表-可pop任意字节的队列-续

前言

这篇文章是针对,上篇文章链表-可pop任意字节的队列的后续。
主要是对代码进行了优化,优化的点有下面几项

  • 对代码结构进行了调整。

    上次的版本只是一个简单得雏形,这份代码进一步分成了头文件和实现文件。

  • 优化了类的封装性,对具体实现进行了隐藏。

    因为这个功能是通过头结点的链表的实现的,而在上分代码中,使用者可以通过调用的到头结点信息,然后使用者就可以对这个链表进行任意操作,这样就很危险。所以在这版中,将所有入口都改成了void *数据类型,在实现的地方进行类型转换,增加了类的安全性。

具体代码

头文件

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>

/*
 * MemLink Brief Description
 *
 * link0
 * addr(id, sum, size)->node->node->node->node...
 * 
 * link1
 * addr(id, sum, size)->node->node->node->node...
 * 
 * link2
 * addr(id, sum, size)->node->node->node->node...
 * 
 */

class MemLink
{
public:
    MemLink() { m_mem_link.clear(); }
    ~MemLink() {}

    //create link by id
    int create_link(int id);
    //get link addr, for first para is *addr, !!need to traverse!!
    void *get_addr_by_id(int id);
    //get link addr, for first para is *addr
    void *get_addr_by_index(int index);
    int push_data(void *addr, char *data, int len);
    int read_data(void *addr, char *data, int len);
    int pop_data(void *addr, char *data, int len);

    //delete one link
    int delete_link(void *addr);
    //delete all links
    int delete_memlink();

    //get link description
    int get_id_by_addr(void *addr);
    int get_size_by_addr(void *addr);
    int get_num_by_addr(void *addr);
    int get_memlink_num();
    void printf_memlink_status();

    void link_test();

private:
    std::vector<void *> m_mem_link;

    void *mk_node(int id, char *data, int len);
    int free_node(void *node);
    int push(void *addr, void *node);
    void *pop(void *addr);
    void printf_link(void *addr);   //debug, when data is ascii, can call it
};

实现文件

#include "test_mem_link.h"

typedef struct Node
{
    int id;     //unique id
    int pos;    //data start pos
    int size;   //data size --> value size = size-pos
    int num;    //for head only
    char *data;
    struct Node *next;
} Node;

void *MemLink::mk_node(int id, char *data, int len)
{
    Node *node = new Node;
    if (node == NULL) {
        perror("new Node failed\n");
        return NULL;
    }
    if (data != NULL) {
        node->data = new char[len]();
        if (node->data == NULL) {
            perror("node->data = new failed");
            return NULL;
        }
        memcpy(node->data, data, len);
    }
    else node->data = NULL;

    node->id = id;
    node->pos = 0;
    node->size = len;
    node->num = 0;
    node->next = NULL;
    return (void *)node;
}

int MemLink::free_node(void *addr)
{
    Node *node = (Node *)addr;
    if (node->data != NULL)
        delete[] node->data;
    node->data = NULL;
    if (node)
        delete node;
    node = NULL;
    return 0;
}

void *MemLink::get_addr_by_id(int id)
{
    int i = 0;
    for (i = 0; i < (int)m_mem_link.size(); i++) {
        if (id == ((Node *)m_mem_link[i])->id) {
            return (Node *)m_mem_link[i];
        }
    }
    return NULL;
}

int MemLink::create_link(int id)
{
    Node *node_ret = (Node *)get_addr_by_id(id);
    if (node_ret != NULL) {
        printf("link id[%d] exist, can't create it\n", id);
        return -1;
    }

    printf("link id[%d] not exist, create it\n", id);
    Node *node = (Node *)mk_node(id, NULL, 0);
    if (node == NULL) {
        printf("mk_node failed!\n");
    }
    else {
        m_mem_link.push_back((void *)node);
    }

    return 0;
}

int MemLink::push(void *addr, void *node)
{
    Node *p = (Node *)addr;
    while (p->next != NULL) {
        p = p->next;
    }

    ((Node *)node)->next = p->next;
    p->next = ((Node *)node);

    ((Node *)addr)->size += ((Node *)node)->size;
    ((Node *)addr)->num++;
    return 0;
}

int MemLink::get_id_by_addr(void *addr)
{
    return ((Node *)addr)->id;
}
int MemLink::get_size_by_addr(void *addr)
{
    return ((Node *)addr)->size;
}
int MemLink::get_num_by_addr(void *addr)
{
    return ((Node *)addr)->num;
}

int MemLink::push_data(void *addr, char *data, int len)
{
    int id = get_id_by_addr(addr);
    Node *phead = (Node *)addr;
    Node *node = (Node *)mk_node(id, data, len);
    if (node == NULL) {
        printf("mk_node failed!\n");
    }
    push(phead, node);
}

void *MemLink::pop(void *addr)
{
    Node *p = ((Node *)addr)->next;
    if (p != NULL) {
        ((Node *)addr)->size -= p->size - p->pos;
        ((Node *)addr)->next = p->next;
        ((Node *)addr)->num--;
        p->next = NULL;
        return p;
    }
    return NULL;
}

void *MemLink::get_addr_by_index(int index)
{
    return m_mem_link[index];
}

int MemLink::read_data(void *addr, char *data, int len)
{
    Node *phead = (Node *)addr;
    if (len > phead->size) {
        printf("pop data len > link size, read data failed\n");
        return -1;
    }

    int i_read = 0;
    Node *p = phead->next;
    while (1) {
        if (p == NULL) {
            printf("p == NULL\n");
            break;
        }

        if (i_read + p->size - p->pos > len) {
            //printf(" < len\n");
            memcpy(&data[i_read], &p->data[p->pos], len - i_read);
            break;
        }

        if (i_read + p->size - p->pos == len) {
            //printf(" = len\n");
            memcpy(&data[i_read], &p->data[p->pos], p->size - p->pos);
            break;
        }

        if (i_read + p->size - p->pos < len) {
            //printf(" > len\n");
            memcpy(&data[i_read], &p->data[p->pos], p->size - p->pos);
            i_read += p->size - p->pos;
            p = p->next;
        }
    }
    return 0;
}

int MemLink::pop_data(void *addr, char *data, int len)
{
    Node *phead = (Node *)addr;
    if (len > phead->size) {
        printf("pop data len > link size, read data failed\n");
        return -1;
    }

    Node *phead_tmp = phead;
    int i_read = 0;
    while (1) {
        Node *p = phead_tmp->next;
        if (p == NULL) {
            printf("p == NULL\n");
            break;
        }

        if (i_read + p->size - p->pos > len) {
            // printf(" > len\n");
            memcpy(&data[i_read], &p->data[p->pos], len - i_read);

            p->pos += len - i_read;
            phead->size -= len - i_read;
            break;
        }

        if (i_read + p->size - p->pos == len) {
            // printf(" = len\n");
            memcpy(&data[i_read], &p->data[p->pos], p->size - p->pos);

            phead->size -= p->size - p->pos;
            phead_tmp->next = p->next;
            phead->num--;
            free_node(p);
            p = NULL;
            break;
        }

        if (i_read + p->size - p->pos < len) {
            // printf(" < len\n");
            memcpy(&data[i_read], &p->data[p->pos], p->size - p->pos);
            i_read += p->size - p->pos;

            phead->size -= p->size - p->pos;
            phead_tmp->next = p->next;
            phead->num--;
            free_node(p);
            p = NULL;
        }
    }
    return 0;
}

int MemLink::get_memlink_num()
{
    return m_mem_link.size();
}

void MemLink::printf_memlink_status()
{
    int i = 0;
    for (i = 0; i < (int)m_mem_link.size(); i++) {
        Node *phead = (Node *)m_mem_link[i];
        printf(">link: id: %d, pos: %d, num: %d, size: %d, data: %s\n", phead->id,
                            phead->pos, phead->num, phead->size, phead->data);
    }
}

void MemLink::printf_link(void *addr)
{
    Node *phead = (Node *)addr;
    printf(">link: id: %d, pos: %d, num: %d, size: %d, data: %s\n", phead->id,
                        phead->pos, phead->num, phead->size, phead->data);
    Node *p = phead->next;
    while (p) {
        printf("node:  id: %d, pos: %d, size: %d\n", p->id, p->pos, p->size);
        p = p->next;
    }
}

int MemLink::delete_link(void *addr)
{
    int id = get_id_by_addr(addr);
    Node *phead = (Node *)addr;
    Node *p = phead->next;
    while (phead->next) {
        p = phead->next;
        phead->next = p->next;
        free_node(p);
    }

    std::vector<void *>::iterator it;
    for (it = m_mem_link.begin(); it != m_mem_link.end(); ) {
        //if (((Node *)it)->id == get_id_by_addr(addr)))
        if (*it == addr) {
            //printf("%d = %d\n", get_id_by_addr(*it), get_id_by_addr(addr));
            it = m_mem_link.erase(it);
            break;
        }
        else it++;
    }

    free_node(phead);
    printf("delete id[%d] link\n", id);

    return 0;
}

int MemLink::delete_memlink()
{
    int i = 0;
    for (i = 0; i < (int)m_mem_link.size(); i++) {
        int id = get_id_by_addr(m_mem_link[i]);
        Node *phead = (Node *)m_mem_link[i];
        Node *p = phead->next;
        while (phead->next) {
            p = phead->next;
            phead->next = p->next;
            free_node(p);
        }
        printf("delete id[%d] link\n", id);
        free_node(phead);
    }
    m_mem_link.clear();
    return 0;
}

void MemLink::link_test()
{
    int id = 10;
    create_link(id);

    // push
    char tmp[10] = {0};
    void *addr = get_addr_by_id(id);
    strcpy(tmp, "111222333");
    push_data(addr, tmp, strlen(tmp));
    strcpy(tmp, "444555666");
    push_data(addr, tmp, strlen(tmp));
    strcpy(tmp, "777888999");
    push_data(addr, tmp, strlen(tmp));

    push_data(addr, (char *)"1", strlen("1"));
    push_data(addr, (char *)"2", strlen("2"));
    push_data(addr, (char *)"3", strlen("3"));
    push_data(addr, (char *)"4", strlen("4"));
    push_data(addr, (char *)"5", strlen("5"));
    push_data(addr, (char *)"6", strlen("6"));
    push_data(addr, (char *)"7", strlen("7"));

    id = 20;
    create_link(id);
    addr = get_addr_by_id(id);
    push_data(addr, (char *)"8", strlen("8"));
    push_data(addr, (char *)"9", strlen("9"));
    push_data(addr, (char *)"10", strlen("10"));

    id = 30;
    create_link(id);
    addr = get_addr_by_id(id);
    push_data(addr, (char *)"11", strlen("11"));
    push_data(addr, (char *)"12", strlen("12"));
    push_data(addr, (char *)"13", strlen("13"));


    printf_memlink_status();
    int memlink_num = get_memlink_num();
    printf("\nmemlink_num = %d\n", memlink_num);
    for (int i = 0; i < memlink_num; i++) {
        void *addr = get_addr_by_index(i);
        // printf_link(addr);
        if (get_id_by_addr(addr) == 10) {
            // //pop
            // Node *p4 = pop(phead);
            // printf("pop size = %d\n", p4->size);
            // free_node(p4);

            char read_tmp[11 + 1] = {0};
            pop_data(addr, read_tmp, 11);
            printf("read_data = %s\n", read_tmp);

            char read_tmp2[8 + 1] = {0};
            pop_data(addr, read_tmp2, 8);
            printf("read_data = %s\n", read_tmp2);
            // printf_link(addr);
        }
    }

    addr = get_addr_by_id(20);
    delete_link(addr);

    delete_memlink();
}

int main()
{
    MemLink ml;
    ml.link_test();

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chasentech

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值