用函数递归调用删除结点。
void deletex(linklist &L,int x){
if(L==NULL) return;
lnode *p;
if(L->data==x){
p=L;
L=L->next;
free(p);
deletex(L,x);
}
else deletex(L->next,x);
}
注意删除结点的时候可能断链。
void deletex2(linklist &L,int x){
lnode *p=L->next,*pre=L,*q;
while(p){
if(p->data==x){
q=p;
p=p->next;
pre->next=p;
free(q);
}else{
pre=p;
p=p->next;
}
}
}
利用函数调用的特性反向输出。
void r_print(linklist L){
if(L!=NULL)
{
r_print(L->next);
cout<<(L->data)<<" ";
}
else return;
}
void r_ignore_node(linklist L){
if(L->next!=NULL){
r_print(L->next);
}
}
void delete_min(linklist L){
lnode *p=L->next,*pre=L;
lnode *minp=p,*minpre=pre;
while(p){
if(p->data<minp->data){
minp=p;
minpre=pre;
}else{
p=p->next;
pre=pre->next;
}
}
minpre->next=minp->next; //删除最小值结点
free(minp);
}
很重要的基础:头插法
void head(linklist &L){
lnode *p=L->next,*r;
L->next=NULL;
while(p){
r=p->next; //记录下一结点
p->next=L->next;
L->next=p;
p=r;
}
}
使用插入排序的思想,将头置空之后,扫描最小元素,然后使用尾插法插入头中。
void insert_sort(linklist &L){
lnode *p=L->next,*r=p->next,*pre;
p->next=NULL;
p=r;
while(p){
r=p->next;
pre=L;
while(pre->next!=NULL&&pre->next->data<p->data){
pre=pre->next;
}
p->next=pre->next;
pre->next=p;
p=r;
}
}
见2题的删除代码,改下if语句即可。
void delete_x_m_n(linklist &L,int m, int n){
lnode *p=L->next,*pre=L,*q;
while(p){
if(p->data<n&&p->data>m){
q=p;
p=p->next;
pre->next=p;
free(q);
}else{
pre=p;
p=p->next;
}
}
}
linklist find_same_dot(linklist L1,linklist L2){
linklist longlist, shortlist;
int dist=0;
int len1=length(L1),len2=length(L2);
if(len1>len2){
longlist=L1;
shortlist=L2;
dist=len1-len2;
}else{
longlist=L2;
shortlist=L1;
dist=len2-len1;
}
while(dist--) longlist=longlist->next;
while(longlist){
if(longlist->data==shortlist->data&&longlist->next->data==shortlist->next->data)
return longlist;
else{
longlist=longlist->next;
shortlist=shortlist->next;
}
}
return NULL;
}
见6题
void min_output(linklist L){
while(L->next){
lnode *pre=L,*p=L->next;
lnode *minpre=pre, *minp=p;
while(p){
if(p->data<minp->data){
minp=p;
minpre=pre;
}
p=p->next;
pre=pre->next;
}
cout<<minp->data<<" ";
minpre->next=minp->next;
free(minp);
}
}
第一种方法是在A中直接删除。
linklist split_1_1(linklist &A){
linklist B = (linklist)malloc(sizeof(lnode));
B->next=NULL;
lnode *p=A->next,*ra=A;
lnode *rb=B,*q;
while(p){
//向后移一个
ra=p;
p=p->next;
//从A中删除结点
q=p;
ra->next=p->next;
p=p->next;
//利用尾插法将结点插入B中
rb->next=q;
rb=rb->next;
}
ra->next=NULL;
rb->next=NULL;
return B;
}
第二种方法是把A的头拿下来,再选最小的排在A后。=尾插==
linklist split_1_2(linklist &A){
linklist B = (linklist)malloc(sizeof(lnode));
B->next=NULL;
lnode *p=A->next,*ra=A;
lnode *rb=B;
//把表头摘下来
A->next=NULL;
while(p){
//结点给A
ra->next=p;
ra=ra->next;
p=p->next;
//结点给B
rb->next=p;
rb=rb->next;
p=p->next;
}
ra->next=NULL;
rb->next=NULL;
return B;
}
第一种方法同上
linklist split_1_1(linklist &A){
linklist B = (linklist)malloc(sizeof(lnode));
B->next=NULL;
lnode *p=A->next,*ra=A;
lnode *rb=B,*q;
while(p){
//向后移一个
ra=p;
p=p->next;
//从A中删除结点
q=p;
ra->next=p->next;
p=p->next;
//利用头插法将结点插入B中
q=p->next;
p->next=rb->next;
rb->next=p;
p=q;
}
ra->next=NULL;
return B;
}
第二种方法同上
linklist split_2_1(linklist &A){
linklist B = (linklist)malloc(sizeof(lnode));
B->next=NULL;
lnode *p=A->next,*ra=A;
lnode *rb=B,*q;
//把表头摘下来
A->next=NULL;
while(p){
//结点给A
ra->next=p;
ra=ra->next;
p=p->next;
//结点给B
if(p){
q=p->next;
p->next=rb->next;
rb->next=p;
p=q;
}
}
ra->next=NULL;
//b是头插法所以最后指向是为NULL
return B;
}
简单代码,只不过要注意的p是要删除结点的前一个结点,判断的时候别判断错了。
void del_same(linklist &L){
lnode *p=L->next,*q;
if(p==NULL) return;
while(p->next){
q=p->next;
if(p->data==q->data){
p->next=q->next;
free(q);
}else{
p=p->next;
}
}
}
void merge(linklist &L1,linklist &L2)
{
lnode *p1=L1->next,*p2=L2->next,*r;
L1->next=NULL;
while(p1&&p2)
{
if(p1->data<=p2->data)
{
r=p1->next;
p1->next=L1->next;
L1->next=p1;
p1=r;
}
else
{
r=p2->next;
p2->next=L1->next;
L1->next=p2;
p2=r;
}
}
if(p1) p2=p1;
while(p2)
{
r=p2->next;
p2->next=L1->next;
L1->next=p2;
p2=r;
}
free(L2);
}
linklist merge_same(linklist &A,linklist &B){
lnode *p=A->next,*q=B->next;
lnode *r,*s;
linklist C = (linklist)malloc(sizeof(lnode));
r=C;
while(p&&q){
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=r->next;
p=p->next;
q=q->next;
}
}
r->next=NULL;
return C;
}
void intersection(linklist &A,linklist &B){
lnode *p=A->next,*q=B->next;
lnode *r=A,*temp;
while(p&&q){
if(p->data<q->data){
temp=p;
p=p->next;
free(temp);
}else if(p->data>q->data){
temp=q;
q=q->next;
free(temp);
}else{
//相等的时候保留A中相同元素
r->next=p;
r=r->next;
p=p->next;
//删除B中相同的元素
temp=q;
q=q->next;
free(temp);
}
}
while(p){
temp=p;
p=p->next;
free(temp);
}
while(q){
temp=q;
q=q->next;
free(temp);
}
r->next=NULL;
}
朴素kmp,也有所说bf的
bool simple_kmp(linklist &A,linklist &B){
lnode *p=A->next,*q=B->next,*r=A->next;
while(p&&q){
if(p->data!=q->data){
r=r->next;
p=r;
q=A->next;
}else{
p=p->next;
q=q->next;
}
}
if(q) return false;
else return true;
}
循环链表就方便了,能找前驱和后继,两个指针同时移动判断值即可。
bool symmetry(linklist L)
{
lnode *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 false;
}
return true;
}
注意头尾即可
void add(linklist &h1,linklist &h2)
{
lnode *p=h1->next,*q=h2->next;
while(p->next!=h1)
{
p=p->next;
}
while(q->next!=h2){
q=q->next;
}
p->next=h2->next;//初始化的链表带头结点,若不带h2即可
q->next=h1;
}
void find_min(linklist &L){
while(L->next!=L){
lnode *pre=L,*p=L->next;
lnode *minpre=pre, *minp=p;
while(p!=L){
if(p->data<minp->data){
minp=p;
minpre=pre;
}
p=p->next;
pre=pre->next;
}
cout<<minp->data<<" ";
minpre->next=minp->next;
free(minp);
}
free(L);
}
lnode* findd(lnode *L)
{
lnode *f=L,*s=L;
while(s!=NULL&&f->next!=NULL)
{
s=s->next;
f=f->next->next;
if(s->data==f->data) break; //可以直接设置指针,但是我初始化的有单链表为int a[15]={1,2,3,4,5,6,7,8,9,4,5,6,7,8,9};故用这种方法
}
if(s==NULL||f->next==NULL) return NULL;
lnode *p=L,*q=s;
while(p->data!=q->data)
{
p=p->next;
q=q->next;
}
return p;
}
int findk(linklist &L, int k){
lnode *p=L,*q=L;
int count=0;
while(p){
if(count<k) count++;
else q=q->next;
p=p->next;
}
if(count<k) return 0;
else cout<<"kth to last position: "<<q->data;
return 1;
}
typedef struct lnode{
int data;
struct lnode *next;
}lnode,*linklist;
lnode * find_addr(linklist str1, linklist str2){
lnode *p,*q;
int m=length(str1);
int n=length(str1);
for(p=str1;m>n;m--) p=p->next;
for(q=str2;m<n;n--) q=q->next;
while (p->next!=NULL&&q->next!=NULL)
{
p=p->next;
q=q->next;
}
return p->next;
}
要求时间复杂度尽可能高➡️空间换时间
void same(linklist &L,int n)
{
lnode *p=L;
int *q;
q=(int *)malloc(sizeof(int)*(n+1));
for(int i=0;i<n+1;i++) *(q+i)=0;
int s;
lnode *f;
while(p->next!=NULL)
{
s=abs(p->next->data);
if(*(q+s)==0)
{
*(q+s)=1;
p=p->next;
}
else
{
f=p->next;
p->next=f->next;
free(f);
}
}
free(q);
}
void change(linklist &L){
lnode *p,*q,*r,*s;
p=q=L;
while (q->next)
{
p=p->next;
q=q->next;
if(q->next) q=q->next;
}
q=p->next; //p现在在中间结点
p->next=NULL; //把后半段摘下来,逆置之后分别遍历两个链表插入指定位置
while (q) //头插法实现原地逆置
{
r=q->next; //暂存后继结点
q->next=p->next; //将q结点放在头结点p之后
p->next=q;
q=r;
}
s=L->next; //插入点
q=p->next; //后半段数据点
p->next=NULL;
while(q){
r=q->next;
q->next=s->next;
s->next=q;
s=q->next;
q=r;
}
}