题目要求:
我在一开始的代码实现:
#include<stdio.h>
#include<stdlib.h>
#define ElemType int
typedef struct DNode{
ElemType data;
int freq;
struct DNode* pred;
struct DNode* next;
}DNode,*DinkList;
//先用尾插法构造非循环双链表:
DinkList List_TailInsert(DinkList &L)
{
int x;
L=(DinkList)malloc(sizeof(DNode));
L->next=NULL;
L->pred=NULL;
DNode *s,*r=L;
scanf("%d",&x);
while(x!=9999)
{
s=(DNode*)malloc(sizeof(DNode));
s->data=x;
s->freq=0;
s->next=r->next;
s->pred=r;
r->next=s;
r=s;
scanf("%d",&x);
}
r->next=NULL;
return L;
}
//本题的的解答:
void BubbleSort(DinkList &L,ElemType x)
{
DNode *p,*q=NULL;
int f,d;
while(1)
{
if(L->next==q)return;
for(p=L->next;p->next!=q;p=p->next)
{
if(p->freq<=p->next->freq)
{
if(p->next->data==x)
{
d=p->data;
p->data=p->next->data;
p->next->data=d;
}
f=p->freq;
p->freq=p->next->freq;
p->next->freq=f;
}
}
q=p;
}
return;
}
DNode* Locate(DinkList &L,ElemType x)
{
DNode *p=L->next;
while(p!=NULL)
{
if(p->data==x)
{
p->freq++;
break;
}
p=p->next;
}
BubbleSort(L,x); //经过改进的链表冒泡排序,要考虑到最后一次访问的值
return p;
}
//..............................................
void ShowList(DinkList L)
{
printf("\n输出处理之后的链表:\n");
DNode* p=L->next;
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
return;
}
int main()
{
DinkList L;
int x;
printf("构造非循环双向链表L:\n");
L=List_TailInsert(L);
printf("现在开始随机访问各个节点:\n\n");
while(1)
{
printf("输入想要访问的元素:\n");
scanf("%d",&x);
if(x==9999)
{
printf("\n访问结束!\n");
break;
}
DNode *p=Locate(L,x);
if(p!=NULL)
if(p->data==x)printf("\n查询正确\n");
ShowList(L);
}
return 0;
}
能够运行,但问题是这代码实在太长了,看了王道的视频之后再写一次:
#include<stdio.h>
#include<stdlib.h>
#define ElemType int
typedef struct DNode{
ElemType data;
int freq;
struct DNode* pred;
struct DNode* next;
}DNode,*DinkList;
//先用尾插法构造非循环双链表:
DinkList List_TailInsert(DinkList &L)
{
int x;
L=(DinkList)malloc(sizeof(DNode));
L->next=NULL;
L->pred=NULL;
DNode *s,*r=L;
scanf("%d",&x);
while(x!=9999)
{
s=(DNode*)malloc(sizeof(DNode));
s->data=x;
s->freq=0;
s->next=r->next;
s->pred=r;
r->next=s;
r=s;
scanf("%d",&x);
}
r->next=NULL;
return L;
}
//本题的的解答:
DNode* Locate(DinkList &L,ElemType x)
{
DNode *p=L->next,*q;
while(p&&p->data!=x)p=p->next;
if(!p)
{
printf("\n不存在值为%d的节点!\n",x);
return NULL;
}
else{
p->freq++;
if(p->next!=NULL)
{
p->next->pred=p->pred;
}
p->pred->next=p->next;
q=p->pred;
while(q!=L&&q->freq<=p->freq)q=q->pred;
p->next=q->next;
q->next->pred=p;
p->pred=q;
q->next=p;
}
return p;
}
//..............................................
void ShowList(DinkList L)
{
printf("\n输出处理之后的链表:\n");
DNode* p=L->next;
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
return;
}
int main()
{
DinkList L;
int x;
printf("构造非循环双向链表L:\n");
L=List_TailInsert(L);
printf("现在开始随机访问各个节点:\n\n");
while(1)
{
printf("输入想要访问的元素:\n");
scanf("%d",&x);
if(x==9999)
{
printf("\n访问结束!\n");
break;
}
DNode *p=Locate(L,x);
if(p!=NULL)
if(p->data==x)printf("\n查询正确\n");
ShowList(L);
}
return 0;
}
不过这代码里有个小bug。在执行p->next->pred=p->pred;这一句操作的时候,如果p是最后一个节点,不做判断就直接执行这个操作就会导致段错误,当然对考试应该没啥影响,但如果是做开发,还是防着点吧。