39.png

    1. /*
    2. 给一个非循环双向链表增加一个freq值,用以表示它的访问频率,每访问一次freq就+1,然后需要将该链表按照非增的顺序
    3. 排列,同时最近访问的节点排在相同频度节点的前面,以便使频繁访问的节点总是靠近表头。试编写符合上述要求的Locate(L,x)
    4. 函数,该运算为函数过程,返回找到节点的地址,类型为指针型。
    5. 分析:
    6. 这道题咋一看很唬人,还引入了一个新概念,其实并不难,拆分开来其实就是 查找+排序;我们需要先找到我们要访问的节点
    7. ,更改它的freq值,然后按照freq值的大小从表头寻找插入位置,这样便完成了一次locate操作。
    8. */
    9. struct Link {
    10. int data;
    11. struct Link *pre;
    12. struct Link *next;
    13. int freq;
    14. };
    15. #define _CRT_SECURE_NO_WARNINGS
    16. #include <stdio.h>
    17. #include <stdlib.h>
    18. void locate(Link *h,int num) {
    19. int flag = 0;//找到标志
    20. struct Link *pre=h, *p = h->next, *t,*preQ=h,*q;
    21. while (p) {
    22. if (p->data==num) {//如果找到
    23. flag = 1;//表示找到
    24. p->freq++;//freq+1
    25. t = p;//将该节点保存起来
    26. if (p->next) {
    27. pre->next = p->next;//将该节点抠出来
    28. p->next->pre = pre;
    29. }
    30. else {
    31. pre->next = NULL;//这里也要注意,如果我们查找的节点是最后一个节点,我们要将next指向NULL,不然之后遍历时会出问题
    32. }
    33. q = h->next;//这里需要注意,q应该始终指向改变了的首节点,之前我在定义时去指定,会出现bug
    34. while (q) {//进行排序
    35. if (t->freq >= q->freq) {//当找到的节点的freq大于等于当前遍历节点时,插入
    36. t->next = q;
    37. q->pre = t;
    38. preQ->next = t;
    39. t->pre = preQ;
    40. break;
    41. }
    42. preQ = q;
    43. q = q->next;
    44. }
    45. break;
    46. }
    47. pre = p;
    48. p = p->next;
    49. }
    50. if (!flag) {
    51. printf("未找到该元素,序列不做改变");
    52. }
    53. }
    54. int main() {
    55. int n, data,num;
    56. struct Link *head = (struct Link *)malloc(sizeof(struct Link));
    57. head->next = NULL;
    58. head->pre = NULL;
    59. struct Link *p = head;
    60. printf("请输入节点个数:n=");
    61. scanf("%d", &n);
    62. for (int i = 0; i < n; i++) {
    63. printf("请输入第%d个节点值:", i + 1);
    64. scanf("%d", &data);
    65. struct Link *newP = (struct Link*)malloc(sizeof(struct Link));
    66. newP->data = data;
    67. newP->pre = p;
    68. newP->freq = 0;
    69. p->next = newP;
    70. p = newP;
    71. }
    72. p->next = NULL;
    73. do {
    74. printf("请输入要查找的值,输入9999代表结束:num=");
    75. scanf("%d",&num);
    76. if (num == 9999)continue;//如果num=9999,跳入下一次循环
    77. locate(head,num);
    78. //p = head->next;
    79. printf("调整后链表为:\n");
    80. while (p) {
    81. printf("%d ",p->data);
    82. p = p->next;
    83. }
    84. } while (num!=9999);
    85. return 0;
    86. }