设有一头指针为L的带有表头结点的非循环双向链表,其每个结点中除有pred(前驱指针)、data(数据)和next(后继指针)域外,还有一个访问频度域freq。在链表被起用前,其值均初始化为零。每当在链表中进行一次Locate(L,x)运算时,令元素值为x的结点中freq域的值增1,并使此链表中结点保持按访问频度非增(递减)的顺序排列,同时最近访问的结点排在频度相同的结点的最后,以便使频繁访问的结点总是靠近表头。试编写符合上述要求的Locate(L,x)运算的算法,该运算为函数过程,返回找到结点的地址,类型为指针型。
typedef struct DNode{
int data,freq=0;
struct DNode *next,*prior;
}DNode,*DLinkList;
DLinkList Locate(DLinkList &L,ElemType x){
DNode *p=L->next,*pre;
while(p!=NULL&&p->data!=x){ //找到x节点
p=p->next;
}
if(p==NULL) exit(0);
else{
p->freq++;
if(p->next!=NULL) p->next->prior=p->prior; //摘出p节点
p->prior->next=p->next;
pre=p->prior;
while(pre!=L&&pre->freq<=p->freq){ //找到第一个频度大于p节点频度的节点
pre=pre->prior;
}
p->next=pre->next; //插入p节点
p->next->prior=p;
pre->next=p;
p->prior=p;
}
return p;
}
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;//单链表
typedef struct DNode{
int data;
struct DNode *next,*prior;
}DNode,*DLinkList;//双链表
//将两个升序链表结合成一个降序链表,头插法。
void MergeSort(LinkList &L1,LinkList &L2){
LNode *p=L1->next,*q=L2->next,*r;
L1->next=NULL;
while(p!=NULL&&q!=NULL){
if(p->data<q->data){
r=p->next;
p->next=L1->next;
L1->next=p;
p=r;
}
else{
r=q->next;
q->next=L1->next;
L1->next=q;
p=r;
}
}
if(p) q=p;
while(q!=NULL){
r=q->next;
q->next=L1->next;
L1->next=q;
q=r;
}
free(L2);
}
//将两个有序链表的公共元素结合成一个链表,要求不破坏原有链表结构。
LinkList Get_Common(LinkList A,LinkList B){
LNode *p=A->next,*q=B->next,*r;
LinkList C=(LinkList)malloc(sizeof(LNode));
r=C;
while(p!=NULL&&q!=NULL){
if(p->data<q->data){
p=p->next;
}
else if(p->data>q->data){
q=q->next;
}
else{
s=(LNode*)malloc(sizeof(LNode));
s->data=p->data; //尾插
r->next=s;
r=s;
p=p->next;
q=q->next;
}
r->next=NULL;
}
}
//判断一个带头双链表是否对称。
int Symmetry(DLinkList L){
DNode *p=L->next,*q=L->prior;
while(p!=q){ //循环结束退出是链长为奇数的情况
if(p.data==q.data){
if(p->next==q) //链长为偶数的情况
return 1;
else{
p=p->next;
q=q->prior;
}
}
else return 0;
}
return 1;
}
//将两个循环单链表头指针为L1和L2,将L2连接到L1之后,仍然保持循环链表形式。
LinkList LinkList(LinkList &L1,LinkList &L2) {
LNode *p=L1,*q=L2;
while(p->next!=L1){
p=p->next;
}
while(q->next!=L2){
q=q->next;
}
p->next=L2;
q->next=L1;
return L1;
}
//重复删除一个带头结点的链表中节点值最小的节点并输出其节点值,直到链表为空。
void Del_Min(LinkList &L){
LNode *p,*minp,*pre,*minpre;
while(L->next!=L){ //循环链表判空条件
p=minp=L->next;
pre=minpre=L;
while(p!=L){
if(p->data<minp->data){
minp=p;
minpre=pre;
}
pre=p;
p=p->next;
}
printf(minp->data);
minpre->next=minp->next;
free(minp);
}
free(L);
}