设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点
void Del_x_recursion(Linklist &L,int x){
if(L==NULL) return;
if(L->data!=x){
Del_x_recursion(L->next,x);
return;
}
LNode *p;
p=L;
L=L->next;
free(p);
Del_x_recursion(L,x);
}
在带头结点的单链表L中,删除所有值为x的结点,并释放其空间,假设值为x的结点不唯一
/**两个指针一次遍历**/
void Del_x_1(Linklist &L,int x){
LNode *p=L->next,*pre=L,*q;
while(p!=NULL){
if(p->data==x){
q=p;
p=p->next;
pre->next=p;
free(q);
}
else{
pre=p;
p=p->next;
}
}
}
设L为带头结点的单链表,编写算法从尾到头反向输出每个结点的值
/**借助栈来实现,每经过一个结点将值压入栈中,再从栈顶输出值即可。**/
void R_Print(Linklist &L){
if(L->next!=NULL)
R_Print(L->next); //递归
printf(L->data);
}
在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点唯一
LinkList Del_Min(Linklist &L){
LNode *pre=L,*p=pre->next;
LNode *minpre=pre;*minp=p; //保存最小值结点及其前驱
while(p!=NULL){
if(p->data<minp->data){
minp=p;
minpre=pre;
}
pre=p;
p=p->next;
}
minpre->next=minp->next;
free(minp);
return L;
}
试将带头结点的单链表就地逆置,即辅助空间复杂度为O(1)
Linklist Reverse_2(Linklist L){
LNode *pre,*p=L->next,*r=p->next;
p->next=NULL; //处理第一个指针
while(r!NULL){//r为空则说明p是最后一个结点
pre=p;
p=r;
r=r->next;
p->next=pre;//指针反转
}
L->next=p; //处理最后一个指针
return L;
}
有一个带头结点的单链表L,设计算法使其元素递增有序
/**结点重排**/
void Sort(Linklist &L){
LNode*p=L->next,*pre;
LNode*r=p->next; //用r保存p后继结点,以保证不断链
p->next=NULL;
p=r;
while(p!=NULL){
r=p->next;
pre=L;
while(pre->next!=NULL&&pre->next->data<p->data)
pre=pre->next;
p->next=pre->next; //把p插入pre后
pre->next=p;
p=r; //扫描原单链表中剩下的结点
}
}
在一个带头结点的单链表中所有元素结点数据值无序,编写程序,删除表中介于给定两个值之间的元素的元素
void RangeDelete(Linklist &L,int min,int max){
LNode *pr=L,*p=L->next; //p为工作指针,pr是其前驱
while(p!=NULL){
if(p->data>min&&p->data<max){
pr->next=p->next;
free(p);
p=pr->next;
}
else{
pr=p;
p=p->next;
}
}
}
给定两个单链表,找出两个链表的公共结点
/**有公共结点也就是说,两个链表从某一结点开始他们的next都指向同一个结点
因为每个结点都只有一个next域**/
//思路:分别遍历找到长度,求出两个长度之差,在长的链表上先遍历长度之差个结点后再同步遍历两个表
Linklist Sesrch_lis_common(Linklist L1,Linklist L2){
int len1=length(L1),len2=length(L2),dist;
Linklist longList,shortList;
if(len1>len2){
longList=L1->next;
shortList=L2->next;
dist=len1-len2;
}
else{
longList=L2->next;
shortList=L1->next;
dist=len2-len1;
}
while(dist--)
longList=longList->next;
while(longList!=NUll){
if(longList==shortList)//找到第一个公共结点
return longList;
else{
longList=longList->next;
shortList=shortList->next;
}
}
return NULL;
}
给定一个带表头结点的单链表head(data,next),试写算法按递增次序输出单链表中各结点的数据元素,
并释放结点所占的存储空间(不允许使用数组作辅助空间)
void Min_Delete(Linklist &head){
while(head->next!=NULL){//循环到只剩头结点
minpre=head;
p=head->next; //p工作指针
while(p->next!=NULL){
if(p->next->data<minpre->next->data)
minpre=p;
p=p->next;
}
printf(minpre->next->data);
u=minpre->next;
minpre->next=u->next;
free(u);
}
free(head);
}
将一个带头结点的单链表A分解成两个带头结点的单链表A和B
使A表中含有原表中序号为奇数的元素,B表含偶数,且保持相对顺序不变
/**设置访问序号变量**/*r尾结点指针
Linklist DisCreate_l(Linklist &A){
int i=0;
Linklist B=(Linklist)malloc(sizeof(LNode)); //创建B表头
B->next=NULL;
LNode *ra=A,*rb=B; //ra rb分别指向将创建的AB表尾部
LNode *p=A->next; //工作指针
A->next=NULL;
while(p!=NULL){
i++;
if(i%2==0){
rb->next=p;
rb=p;
}
else{
ra->next=p;
ra=p;
}
p=p->next;
}
ra->next=NULL;
rb->next=NULL;
return B;
}
在递增有序的线性表中,有数值相同的元素存在。若存储方式为单链表,设计算法使表中不再有重复的元素
void Del_Same(Linklist &L){
LNode *p=L->next,*q;
if(p==NULL) return;
while(p->next!=NULL){
q=p->next;
if(p->data==q->data){
p->next=q->next;
free(q);
}
else
p=p->next;
}
}
假设有两个元素按序递增的单链表,将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求
利用原来两个单链表的结点存放归并后的单链表
void MergeList(Linklist &La,Linklist &Lb){
LNode *r,*pa=La->next,*pb=Lb->next;
La->next=NULL;
while(pa&&pb)//两链表均不为空时
if(pa->data<=pb->data){
r=pa->next;
pa->next=La->next;
La->next=pa;
pa=r;
}
else{
r=pb->next;
pb->next=La->next;
La->next=pb;
pb=r;
}
if(pa) pb=pa;
while(pb){ //处理剩下一个非空链表,依次插入到La
r=pb->next;
pb->next=La->next;
La->next=pb;
pb=r;
}
free(Lb);
}
设AB两个带头结点的单链表,递增有序,从AB中公共元素产生单链表C
要求不破坏AB结点
void GetCommon(Linklist A,Linkilist B){
LNode *p=A->next,*q=B->next,*r,*s;
Linklist C=(Linklist)malloc(sizeof(LNode));
r=c; //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; //将*s链接到c上 尾插
r=s;
p=p->next;//表AB继续扫描
q=q->next;
}
}
r->next=NULL;
}
已知两个元素递增排列的链表AB,求AB交集并存放在A链表
Linklist Union(Linklist &la,Linklist &lb){
pa=la->next;
pb=lb->next;
pc=la; //结果表中当前合并结点的前驱指针
while(pa&&pb){
if(pa->data==pb->data){
pc->next=pa;
pc=pa;
pa=pa->next;
u=pb; //B中结点释放
pb=pb->next;
free(u);
}
else if(pa->data<pb->data){
u=pa;
pa=pa->next;
free(u);
}
else{
u=pb;
pb=pb->next;
free(u);
}
}
while(pa){ //A未遍历完
u=pa;
pa=pa->next;
free(u); //释放A中剩余结点
}
while(pb){
u=pb;pb=pb->next;
free(u);
}
pc->next=NULL;
free(lb);
return la;
}
两个整数序列A=a1,a2..an,B=b1,b2...bn已存入两个单链表中
判断序列B是否为序列A的连续子序列
/**暴力法**/
int Pattern(Linklist A,Linklist B){
LNode *p=A; //p为链表A的工作指针(假定无头结点
LNode *pre=p; //pre记住每趟比较中A链表的开始结点
LNode *q=B;
while(p&&q){
if(p->data==q->data){
p=p->next;
q=q->next;
}
else{
pre=pre->next;
p=pre;
q=B;
}
}
if(q=NULL)//B已经结束
return 1;//说明是A的连续子序列
else
return 0;
}
设计算法判断带头结点循环双链表是否对称
int Symmetry(DLinklist L){
//本算法从两头扫描循环双链表
DNode *p=L->next,*q=L->prior;
while(p!=q&&q->next!=p)
if(p->data==q->data){
p=p->next;
q=q->prior;
}
else return 0;
return 1;
}
有两个循环单链表,链表头指针分别为h1 h2,编写函数将链表2链接到链表1之后,
要求链接后的链表仍保持循环单链表形式
Linklist Link(Linklist &h1,Linklist &h2){
LNode *p,*q;
p=h1;
while(p->next!=NULL) //寻找h1的尾结点
p=p->next;
q=h2;
while(q->next!=NULL)
q=q->next;
p->next=h2; //将h2链接到h1后
q->next=h1;
return h1;
}
设一个带头结点的循环单链表,其结点值均为正整数
设计算法反复找出单链表结点值最小的结点并输出,然后将该结点删除,直到单链表空为止,在删除表头结点
void Del_ALL(Linklist &L){
LNode *p,*pre,*minp,*minpre;
while(L->next!=L){ //表不空,循环
p=L->next;pre=L;
minp=p;minpre=pre;
while(P!=L){
if(p->data<minp->data){
minp=p;minpre=pre;
}
pre=p;
p=p->next;
}
printf("%d",minp->data);
minpre->next=minp->next;
free(minp);
}
free(L);
}
设头指针为L的带头表头结点的非循环双向链表,其每个结点中除有pre,data,next域外,还有一个访问频度域freq。
在链表被启用前,其值均初始化为零。每当在链表中进行一次locate(L,x)运算时,令元素值为x的结点中freq域的值+1,
并使此链表中结点保持按访问频度非增(递减)的顺序排列,同时最近访问的结点排在频度相同的结点前面,以便使频繁
访问的结点总是靠近表头。试编写符合上述要求的locate(L,x)的算法,该运算为函数过程,返回找到结点的地址,类
型为指针型
DLinkist Locate(DLinklist &L,int x){
DNode *p=L->next,*q;
while(p&&p->data!=x)
p=p->next;
if(!p){
printf("不存在值为x的结点\n");
exit(0);
}
else{
p->freq++;
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;
}
带头结点的单链表[data,link]
假设只给出头指针list,在不改变链表的前提下,设计算法查找链表中倒数第k个位置
上的结点,查找成功则输出data值,返回1,否则返回0
typedef struct LNode{
int data;
sttuct Lnode *link;
}*Linklist;
int Search_k(Linklist list,int k){
Linklist p=list->link,q=list->link;
int count=0;
while(p!=NULL){ //遍历链表直到最后一个结点
if(count<k) count++;//计数,若count<k则只移动p
else q=q->link;
p=p->link;
}
if(count<k) return 0;
else{
printf("%d",q->data);
return 1;
}
}
假定采用带头结点的单链表保存单词,当两个单词有相同后缀时,则可共享相同的后缀存储空间
设str1 str2分别指向两个单词所在单链表的头结点,找出由str1 str2所指向两个链表共同后缀起始位置
LinkNode *Find_1st_Common(LinkList str1,Linklist str2){
int len1=length(str1),len2=length(str2);
LinkNode *q,*p;
for(p=str1;len1>len2;len1--){
p=p->next;
}
for(q=str2;len2>len1;len2--){
q=q->next;
}
while(p->next!=q->next&&p->next!=NULL){
p=p->next;
q=q->next;
}
return p->next;
}
单链表保存了m个整数,结点结构为[data][link],且|data|<n(n为正整数)
设计时间复杂度高效算法,对于链表中data绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点
typedef struct node{
int data;
struct node *link;
}NODE;
typedef NODE *PNODE;
void func(PNODE h,int n){
PNODE p=h,r;
int *q,m;
q=(int*)malloc(sizeof(int)*(n+1));
for(int i=0;i<n+1;i++)
*(q+i)=0; //数组元素初位置0 q为数组*(q+i)=q[i]
while(p->link!=NULL){
m=p->link->data>0?p->link->data:-p->link->data;
if(*(q+m)==0){
//判断该结点的data是否已出现
*(q+m)=1; //首次出现
p=p->next;
}
else{
r=p->link;
//delete
p->link=r->link;
free(r);
}
}
free(q);
}