双向链表的应用—实现根据使用频率安排元素位置的功能

本文探讨了如何利用双向链表来实现一个功能,即将最常使用的元素移动到列表的头部。通过locateorder()函数,当元素使用频率不为0时,查找并插入比当前元素频率高的节点,以此优化用户体验。
摘要由CSDN通过智能技术生成

平时使用音乐播放器时,播放列表中的歌曲可以很方便地进行增添,删除,去重等操作。但其本质都可以抽象成一个双向链表。为了更方便用户的使用,我认为还可以增加一个将最常播放的音乐放在播放列表的头部的功能,那么如何实现呢?请看代码:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int status;
typedef int elemtype;
typedef struct node{
    elemtype data;
    int freq;
    struct node * next;
    struct node * prior;
}node;
typedef struct node* dlinklist;

status visit(elemtype c){
    printf("%d ",c);
}

/*双向链表初始化*/
status initdlinklist(dlinklist * head,dlinklist * tail){
    (*head)=(dlinklist)malloc(sizeof(node));
    (*tail)=(dlinklist)malloc(sizeof(node));
    if(!(*head)||!(*tail))
        return ERROR;
    /*这一步很关键*/ 
    (*head)->prior=NULL;
    (*tail)->next=NULL;
    (*head)->freq=0;
    (*tail)->freq=0; 
    /*链表为空时让头指向尾*/
    (*head)->next=(*tail);
    (*tail)->prior=(*head);
}

/*判定是否为空*/
status emptylinklist(dlinklist head,dlinklist tail){
    if(head->next==tail)
       return TRUE;
    else
       return FALSE;
} 

/*尾插法创建链表*/ 
status createdlinklist(dlinklist head,dlinklist tail,elemtype data){
    dlinklist pmove=head,qmove=tail,pinsert;
    pinsert=(dlinklist)malloc(sizeof(node));
    if(!pinsert)
        return ERROR;
    else{
        pinsert->data=data;
        pinsert->prior=pmove;
        pinsert->next=pmove->next;
        pmove->next->prior=pinsert;
        pmove->next=pinsert;
    }
}

/*正序打印链表*/ 
status traverselist(dlinklist head,dlinklist tail){
    dlinklist pmove=head->next;
    while(pmove!=tail){
        visit(pmove->data);
        pmove=pmove->next;
    }
    printf("\n");
}

status traverselist2(dlinklist head,dlinklist tail){
    dlinklist pmove=head->next;
    while(pmove!=tail){
        visit(pmove->freq);
        pmove=pmove->next;
    }
    printf("\n");
}

/*在链表头插入元素*/
status inserthead(dlinklist head,dlinklist tail,elemtype data){
    dlinklist pinsert;
    pinsert=(dlinklist)malloc(sizeof(node));
    pinsert->data=data;
    pinsert->next=NULL;
    pinsert->prior=NULL;
    tail->prior->next=pinsert;
    pinsert->prior=tail->prior;
    pinsert->next=tail;
    tail->prior=pinsert;
    return OK;
}

/*按使用频次排序*/ 
status locateorder(dlinklist head,dlinklist tail,elemtype data){
    dlinklist pmove=head->next,qmove;
    while(pmove!=tail&&pmove->data!=data)
        pmove=pmove->next;
    if(pmove==tail){
        printf("未找到\n");
        return ERROR;
    }
    else{
        pmove->freq++;
        qmove=pmove->prior;
        while(qmove!=head&&qmove->freq<pmove->freq)//向前寻找比pmove->freq大的qmove->freq
             qmove=qmove->prior;
        if(qmove->next!=pmove){//如果找到的qmove和pmove不是直接的前驱后继关系
            pmove->next->prior=pmove->prior;
            pmove->prior->next=pmove->next;//将pmove取下
            pmove->prior=qmove;
            pmove->next=qmove->next;
            qmove->next->prior=pmove;
            qmove->next=pmove;//插到qmove之后
        }
    }
}

int main(void){
    dlinklist head,tail,pmove=head;
    int i=0;
    initdlinklist(&head,&tail);
    for(i=0;i<10;i++)
       inserthead(head,tail,i);
    printf("未经过排序的链表为\n");
    traverselist(head,tail);
    printf("在按使用频率排序后的链表为:\n"); 
    locateorder(head,tail,5);
    for(int i=0;i<3;i++){
        locateorder(head,tail,6);
    }
    traverselist(head,tail);
    printf("各元素使用频率为\n");
    traverselist2(head,tail);
}

要实现这一功能,最重要的函数是locateorder(),其实现思路是:如果某个元素的使用频率不为0,则定义一个向链表头移动的游标,寻找一个比该元素使用频率高的元素,将该元素插到找到的元素之后即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值