双向链表L每次访问元素后,元素按访问频度递减次序排列

/*
问题描述:双向链表L(结点中含有fre频度),每次访问元素后,元素按访问频度递减次序排列
说明: 这个问题题非常向操作系统中应用的一些算法了,比如说涉及到内存、磁盘中数据的访问,换出等。这个链表中保存的是按照最近最常使用的顺序排列的。

*/

#include <iostream>
using namespace std;

typedef struct DNode
{
    int data;   //数据
    DNode *pre,*next;   //前一个,后一个指针
    int fre;        //访问频度,初始化为0
}DNode,*DLinklist;


void CreateDList(DLinklist &Dl)
{
    DNode * head = new DNode,*temp;
    head->fre = -1;
    head->data = -1;
    head->next = NULL;
    head->pre = NULL;

    int val;

    cin>>val;
    while(val != 9999)
    {
        temp = new DNode;

        temp->fre = 0;
        temp->data = val;

        if(head->next != NULL)
             head->next->pre = temp;


        temp->next = head->next;
        head->next = temp;
        temp->pre = head;


       // temp->next = NULL;
       cin>>val;

    }
    Dl = head;
}


//按访问频繁度排序元素
void Locate_x(DLinklist &DL,int x)
{
    DNode * p = DL->next,*temp_pre = NULL,*temp_swa = NULL;

    DNode *swa_bef = NULL,*swa_aft = NULL,*p_bef = NULL,*p_aft = NULL;

   // cout<<"test"<<endl;
    while(p != NULL)
    {
        if(x == p->data)
        {
            ++p->fre;

            temp_pre = p->pre;
            while(temp_pre -> fre != -1 && temp_pre->fre <= p->fre )
            {
                temp_pre = temp_pre->pre;

            }

                temp_swa = temp_pre->next;  //p的元素将放在temp_swa的元素前面


                //如果前移的元素不等于本身
                if(temp_swa != p)
                {
                    //p元素前移
                    swa_bef = temp_swa->pre;    //temp_swa的前一个元素
                    swa_aft = temp_swa->next;   //temp_swa的后一个元素
                    p_bef = p->pre;             //p的前一个元素
                    p_aft = p->next;             //p的后一个元素

                    p_bef->next = p_aft;

                    if(p_aft != NULL)
                        p_aft->pre = p_bef;

                    p->next = temp_swa;
                    p->pre = swa_bef;

                    swa_bef->next = p;

                    swa_bef->next = p;

                    temp_swa->pre = p;

                }


            break;
        }
        else
            p = p->next;

    }

}

//顺序输出单链表中的元素
void PrintDList(DLinklist L)
{
    DNode *p;
    p = L->next;
    while(p!=NULL)
    {
        if(p == L->next)
            cout<<p->data;
        else
            cout<<" "<<p->data;
        p = p->next;
    }
    cout<<endl;
}

总结:对于链表的插入、删除有一点麻烦的就是会涉及到改变指针指向的问题。一不小心就会出现断链等错误。在这里采取了最直接的方法,就是把涉及到的结点都表示出来,这样虽然浪费了一点空间,但是,改变指针就方便多了。

其实在实际应用中还可以考虑一些简便的方法来处理注入交换结点、删除等问题。
比如说对于交换结点,我们可以直接交换其中的值,这样就不用改变指针了。对于删除可以采用一种叫做“懒惰删除”的方法,就是不删除,而是增加一个特殊标志,代表其删除了。这样也能达到简化的效果。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值