每日一题15:双端队列与自调整表

双端队列是一种插入和删除可以既可以在表头也可以表尾进行的一种数据结构,四种基本操作分别为:
push:在表头插入
pop:在表头删除
insert:在表尾插入
eject:在表尾删除
每一种操作的复杂度都为O(1)。通过组合不同插入和删除,双端队列可以作为栈使用,也可以作为队列使用:

#include "stdafx.h"
#include <iostream>

using namespace std;

struct deque_node
{
    int val;
    deque_node* next;
    deque_node* pre;
};

struct my_deque
{
    int count;
    deque_node* head;
    deque_node* tail;
};

my_deque* create_empty_deque()
{
    my_deque* deq = new my_deque;
    deq->head = NULL;
    deq->tail = NULL;
    deq->count = 0;
    return deq;
}

deque_node* create_deque_node(int val)
{
    deque_node* node = new deque_node;
    node->val = val;
    node->pre = NULL;
    node->next = NULL;
    return node;
}

void push(my_deque** deq,int val)
{
    deque_node* node = create_deque_node(val);
    if((*deq)->count == 0)
    {
        (*deq)->tail = node;
        (*deq)->head = node;
    }
    else
    {
        node->next = (*deq)->head;
        (*deq)->head->pre = node;
        (*deq)->head = node;
    }
    ++(*deq)->count;
}

bool pop(my_deque** deq,int& val)
{
    if((*deq)->count == 0) return false;
    if((*deq)->count == 1)
    {
        val = (*deq)->head->val;
        delete (*deq)->head;
        (*deq)->head = (*deq)->tail = NULL;
    }
    else
    {
        deque_node* p = (*deq)->head;
        (*deq)->head = p->next;
        (*deq)->head->pre = NULL;
        val = p->val;
        delete p;
    }
    --(*deq)->count;
    return true;
}

void insert(my_deque** deq,int val)
{
    deque_node* node = create_deque_node(val);
    if((*deq)->count == 0)
    {
        (*deq)->head = node;
    }
    else
    { 
        (*deq)->tail->next = node;
        node->pre = (*deq)->tail;
    }
    (*deq)->tail = node;
    ++(*deq)->count;
}

bool eject(my_deque** deq,int& val)
{
    if((*deq)->count == 0) return false;
    if((*deq)->count == 1)
    {
        val = (*deq)->head->val;
        delete (*deq)->head;
        (*deq)->head = (*deq)->tail = NULL;
    }
    else
    {
        deque_node* p = (*deq)->tail;
        p->pre->next = NULL;
        (*deq)->tail = p->pre;
        val = p->val;
        delete p;
    }
    --(*deq)->count;
    return true;
}

void display(const my_deque* deq)
{
    deque_node* p = deq->head;
    while(p)
    {
        cout<<p->val<<' ';
        p = p->next;
    }
    cout<<endl;
}

void reverse_display(const my_deque* deq)
{
    deque_node* p = deq->tail;
    while(p)
    {
        cout<<p->val<<' ';
        p = p->pre;
    }
    cout<<endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    my_deque* deq = create_empty_deque();
    for (int i = 1; i < 6; ++i)
    {
        push(&deq,i);
    }
    display(deq);
    reverse_display(deq);
    cout<<deq->count<<endl;
    for (int i = 1; i < 6; ++i)
    {
        int val;
        if(pop(&deq,val))
            cout<<val<<' ';
    }
    cout<<endl;
    cout<<deq->count<<endl;

    for (int i = 1; i < 6; ++i)
    {
        insert(&deq,i);
    }
    display(deq);
    reverse_display(deq);
    cout<<deq->count<<endl;
    for (int i = 1; i < 6; ++i)
    {
        int val;
        if(eject(&deq,val))
            cout<<val<<' ';
    }
    cout<<endl;
    cout<<deq->count<<endl;
    return 0;
}

这里写图片描述
自调整表就像是一种规则的表,但是它的插入与删除操作都在表头进行,同时当任一个元素被find访问时,它就被移到表头而不改变其它元素的相对位置。基于链表实现的自调整表比较简单,基于数组实现的则需要更多的小心。

#include "stdafx.h"
#include <iostream>

using namespace std;

const int null_slot = -2;
const int end_slot = -1;

struct list_node
{
    int val;
    int next;
};

struct self_adjust_list
{
    int capacity;
    int size;
    int head;
    list_node* vals;
};

self_adjust_list* create(int capacity)
{
    self_adjust_list* sal = new self_adjust_list;
    sal->vals = new list_node[capacity];
    memset(sal->vals,0,capacity*sizeof(list_node));
    for (int i = 0; i < capacity; ++i)
    {
        sal->vals[i].next = null_slot;
    }
    sal->size = 0;
    sal->head = 0;
    sal->capacity = capacity;
    return sal;
}

bool find(self_adjust_list** sal,int val)
{
    if((*sal)->size == 0) return false;
    int cur = (*sal)->head;
    list_node* p = (*sal)->vals;
    int pre = -1;
    while(cur != end_slot && p[cur].val != val)
    {
        pre = cur;
        cur = p[cur].next;
    }
    if(cur == (*sal)->head) return true;
    if(cur != end_slot)
    {
        p[pre].next = p[cur].next;
        p[cur].next = (*sal)->head;
        (*sal)->head = cur;
        return true;
    }
    return false;
}

void push(self_adjust_list** sal,int val)
{
    if(find(sal,val)) return;

    if((*sal)->size == 0)
    {
        (*sal)->vals[0].val = val;
        (*sal)->vals[0].next = end_slot;

    }
    else
    {
        int i = 0;
        for (; i < (*sal)->capacity; ++i)
        {
            if((*sal)->vals[i].next == null_slot)
                break;
        }
        (*sal)->vals[i].next = (*sal)->head;
        (*sal)->vals[i].val = val;
        (*sal)->head = i;
    }

    ++(*sal)->size;
}

bool pop(self_adjust_list** sal,int &val)
{
    if((*sal)->size < 1) return false;

    list_node* p = &(*sal)->vals[(*sal)->head];
    val = p->val;
    if((*sal)->size > 1)
    {
        (*sal)->head = p->next;
        p->next = null_slot;
    }
    else
    {
        (*sal)->head = 0;
    }
    --(*sal)->size;
    return true;
}


int _tmain(int argc, _TCHAR* argv[])
{
    self_adjust_list* sal = create(20);
    for (int i = 1; i < 6; ++i)
        push(&sal,i);
    cout<<sal->size<<endl;
    for (int i = 10; i > 0; --i)
    {
        cout<<find(&sal,i)<<' ';
    }
    cout<<endl;
    for (int i = 1; i < 20; ++i)
    {
        int val;
        if(pop(&sal,val))
            cout<<val<<' ';
    }
    cout<<endl;
    cout<<sal->size<<endl;
    return 0;
}

这里写图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值