赞
踩
链表的创建分为头插法和尾插法,首先讲解尾插法
尾插法就是我创建输入数的顺序是1-2-3,那么创建的链表就是1-2-3。以L为开头的节点,L-1-NULL,每次输入一个元素,就放入NULL的位置处。
#include<stdio.h> #include<malloc.h> typedef struct node{ int data; struct node *next; }Lnode,*ListNode; void out(ListNode L) { ListNode p=L->next; while(p!=NULL) { printf("%d\n",p->data); p=p->next; } } ListNode create(ListNode &L,int k) { L=(ListNode)malloc(sizeof(Lnode)); int x; ListNode r=L,p; while(k--) { p=(ListNode)malloc(sizeof(Lnode)); scanf("%d",&x); p->data=x; r->next=p; r=p; } r->next=NULL; return L; } int main() { ListNode L; L=create(L,5); out(L); }
我们首先需要创建一个结构体,其中typedef是为了方便起别名,*ListNode创建的对象就为结构体的指针。在创建链表当中有一个通用的操作,就是r=L,后续的操作全部以r进行,不能直接利用L,这样主要是为了保持头结点不变,我们通过r就想线一样,对链表可以进行各种操作。
创建链表输入的顺序为1-2-3,生成的链表则是3-2-1,开始的节点情况是L-NULL插入第一个节点L-1-NULL,插入第二个节点,过程如下,2->next=L->next,这样就把L后面全部节点都串连上去了,2-1-NULL,在用L->next=2,就成为了L-2-1-NULL,以此类推;
ListNode create_tail(ListNode &L) { L=(ListNode)malloc(sizeof(Lnode)); L->next=NULL; int x; scanf("%d",&x); ListNode r=L,p; while(x!=99) { p=(ListNode)malloc(sizeof(Lnode)); p->data=x; p->next=r->next; r->next=p; scanf("%d",&x); } return L; }
在创建链表的时候,使用&L,就是为了可以改变链表。这里连接节点也是先用r=L,在对r各种操作。一定不要直接对L操作,很容易出现逻辑错误。
输出的话也是分为顺序输出和逆序输出。
直接用p接受L的节点,依次遍历即可。
void out(ListNode L)
{
ListNode p=L->next;
while(p!=NULL)
{
printf("%d\n",p->data);
p=p->next;
}
}
使用递归的方式,这样会先递归到最后面的值,然后在输出。利用递归的特点,执行完当前代码全部之后返回上一层。在输出。注意点,调用此函数要传入L->next。因为开始头结点L->data我们不传入值
void out_re(ListNode L)
{
if(L->next!=NULL)
out_re (L->next);
printf("%d",L->data);
}
out_re(L->next)
例如,L1-1-3-5-7-9-NULL ,L2-2-4-6-8-10-NULL合并之后为L1-1-2-3-4-5-6-7-8-9-10-NULL。这种二个链表合并的操作。整体思想很简单,就是先将L1清空。然后依次串连最小的值。只要有其中一个链表遍历完,在单独遍历剩余的一个链表就不需要判断大小了。一定要记得将尾链表的指针指向NULL
ListNode Union_up(ListNode L1,ListNode L2,int k1,int k2) { ListNode p=L1->next,q=L2->next; L1->next=NULL; ListNode m=L1; while(k1>0&&k2>0) { if(p->data<=q->data) { m->next=p; m=p; p=p->next; --k1; } else { m->next=q; m=q; q=q->next; --k2; } } if(k1>0) { while(k1--) { m->next=p; m=p; p=p->next; } } else { while(k2--) { m->next=q; m=q; q=q->next; } } m->next=NULL; return L1; }
找二个递增链表的交集,二个链表都从头遍历,谁小谁往后遍历。相等的话就将它串连起来,一定要注意此时二个链表都要向后走,一但有一个链表遍历完就不会再有交集了。
ListNode union_2(ListNode L1,ListNode L2,int k1,int k2) { ListNode p=L1->next,q=L2->next; L1->next=NULL; ListNode m=L1; while(k1>0&&k2>0) { if(p->data==q->data) { m->next=p; m=p; p=p->next; q=q->next; --k1; --k2; } else if(p->data<q->data) { p=p->next; k1--; } else { q=q->next; k2--; } } m->next=NULL; return L1; }
从头遍历链表,结合头插法的思想,边读边插入。这样就可以实现链表的逆转,
ListNode reserve(ListNode &L)
{
ListNode p=L->next,r;
L->next=NULL;
while(p!=NULL)
{
r=p;
p=p->next;
r->next=L->next;
L->next=r;
}
return L;
}
比如L-1-2-3-4-5-NULL,删除2-4范围内的值。变成L-1-5-NULL,删除结点一般都需要用到二个指针,一个是p=L,另一个q=L->next;当想要删除结点。就直接p->next=q->next跳过这个结点就可以了。
ListNode del_range(ListNode &L,int mink,int maxk) { ListNode p=L,q=L->next; while(q!=NULL) { if(q->data>=mink&&q->data<=maxk) { p->next=q->next; q=q->next; } else { q=q->next; p=p->next; } } p->next=NULL; return L; }
最简单有效的方式就是遍历一次知道长度,然后第二次直接遍历到指定位置。
int length(ListNode L) { ListNode p=L->next; int len=1; while(p->next!=NULL) { len++; p=p->next; } return len; } void out_re_k(ListNode L,int k) { int le=length(L); ListNode p=L->next; le=le-k; while(le--) { p=p->next; } printf("%d",p->data); }
这个时候就需要三个指针,这样就只需要遍历一次就可以删除指定节点,让q=L->next,让t先遍历k次。之后q和t节点同时遍历,这样t节点遍历到链表NULL的位置,q则刚好指到倒数第k个结点。
ListNode del_k(ListNode L,int n) { ListNode p=L,q=L->next; ListNode t=L->next; while(n--) { t=t->next; } while(t!=NULL) { p=p->next; q=q->next; t=t->next; } p->next=q->next; return L; }
L-1-2-3-4-NULL 交换后为L-2-1-4-3-NULL
L-5-2-6-3-6-NULL 交换后为L-2-5-3-6-6-NULL
这种交换的题在链表中分为二种思想,一种交换结点,就是修改链表指针指向。另一种直接交换值,也可以实现此功能
ListNode swap(ListNode L,int k) { ListNode p,q,r=L; int n=int(k/2); for(int i=0;i<n;i++) { p=r->next; q=r->next->next; p->next=q->next; r->next=q; q->next=p; r=r->next->next; } return L; }
链表的排序的话是比较复杂,最简单有效的方式就是交换值来进行排序。简单选择排序的思想就是每趟遍历寻找最小值,依次排序。k是链表长度。t用来存储当前遍历最小的位置。在每次遍历都先默认第一个为最小值。
ListNode select_up(ListNode L,int k) { ListNode p=L->next,q,t; int min; while(--k) { q=p->next; min=p->data; t=NULL; while(q!=NULL) { if(q->data<min) { min=q->data; t=q; } q=q->next; } if(t!=NULL) { t->data=p->data; p->data=min; } p=p->next; } return L; }
以链表中节点的值划分为二个链表,值大于零在链表A,值小于零在链表B,链表分解的核心思想在于要利用一下头结点L,和在创建个头结点B,然后将L小于零的值直接删除移动到B的链表下就可以了。
ListNode split(ListNode L,int k) { ListNode B,p,q,n; q=L; p=L->next; B=(ListNode)malloc(sizeof(Lnode)); B->next=NULL; ListNode r1=B; while(k--) { if(p->data<0) { n=p; q->next=p->next;//这二步就是删除操作 p=p->next; r1->next=n; //这步就是串连的操作==尾插法 r1=n; } else { q=q->next; p=p->next; } } r1->next=NULL; return B; }
这个和上面基本一模一样。就修改了一下判断条件
ListNode split_o(ListNode L,int k) k为长度 { ListNode p,q,n,B; B=(ListNode)malloc(sizeof(Lnode)); B->next=NULL; ListNode r1=B; q=L; p=L->next; int i=1; while(k--) { if(i%2==0) { n=p; q->next=p->next; p=p->next; r1->next=n; r1=n; i++; } else { q=q->next; p=p->next; i++; } r1->next=NULL; } return B; }
简单选择排序的思想就是每一次寻找最小值,从n,n-1,n-2为一行找最小值。这样就可以确保最终的排序就升序的。但是链表直接交换位置不方便,所以找到最小值需要标记当前的位置。
ListNode select_up(ListNode L,int k) { ListNode p=L->next,q,t; int min; while(--k) { q=p->next; min=p->data; t=NULL; while(q!=NULL) { if(q->data<min) { min=q->data; t=q; } q=q->next; } if(t!=NULL) { t->data=p->data; p->data=min; } p=p->next; } return L; }
冒泡排序
ListNode up_sort(ListNode L,int k) { ListNode r=L,p,q; int t=0; while(k--) { q=r->next; p=r->next->next; while(q->next!=NULL) { if(q->data>=p->data) { t=q->data; q->data=p->data; p->data=t; } q=q->next; p=p->next; } } return L; }
ListNode count(ListNode L1,ListNode L2,int k1,int k2) { ListNode r1=L1->next,r2=L2->next; ListNode B,m; B=(ListNode)malloc(sizeof(Lnode)); B->next=NULL; int a=0,b=0,c=0,last=0,t=0; while(k1--&&k2--) { a=r1->data; b=r2->data; r1=r1->next; r2=r2->next; t=a+b+c; m=(ListNode)malloc(sizeof(Lnode)); if(t>=10) { last=t%10; c=1; m->data=last; m->next=B->next; B->next=m; } else { c=0; m->data=t; m->next=B->next; B->next=m; } } if(k1>0) { while(k1--) { a=r1->data; r1=r1->next; a=a+c; if(a<10) { c=0; m=(ListNode)malloc(sizeof(Lnode)); m->data=a; m->next=B->next; B->next=m; } else { c=1; last=a%10; m=(ListNode)malloc(sizeof(Lnode)); m->data=last; m->next=B->next; B->next=m; } } } else { while(k2--) { a=r2->data; r2=r2->next; a=a+c; if(a<10) { c=0; m=(ListNode)malloc(sizeof(Lnode)); m->data=a; m->next=B->next; B->next=m; } else { c=1; last=a%10; m=(ListNode)malloc(sizeof(Lnode)); m->data=last; m->next=B->next; B->next=m; } } } if(c==1) { m=(ListNode)malloc(sizeof(Lnode)); m->data=1; m->next=B->next; B->next=m; } return B; }
链表的通用操作挺多的,比如用到删除就要立马p->next=q->next,q=q->next。等等可以将链表细分化为好几个小模块,遇到一个问题在组合小模块去思考就可以了。
#include<stdio.h> #include<malloc.h> #include<math.h> typedef struct node{ int data; struct node *next; }Lnode,*ListNode; ListNode create(ListNode &L) { L=(ListNode)malloc(sizeof(Lnode)); int x; scanf("%d",&x); ListNode r=L,p; while(x!=99) { p=(ListNode)malloc(sizeof(Lnode)); p->data=x; r->next=p; r=p; scanf("%d",&x); } r->next=NULL; return L; } ListNode create_2(ListNode &L,int k) { L=(ListNode)malloc(sizeof(Lnode)); int x; ListNode r=L,p; while(k--) { p=(ListNode)malloc(sizeof(Lnode)); scanf("%d",&x); p->data=x; r->next=p; r=p; } r->next=NULL; return L; } ListNode Union(ListNode L1,ListNode L2) { ListNode p=L1->next; while(p->next!=NULL) { p=p->next; } p->next=L2->next; return L1; } ListNode up_sort(ListNode L,int k) { ListNode r=L,p,q; int t=0; while(k--) { q=r->next; p=r->next->next; while(q->next!=NULL) { if(q->data>=p->data) { t=q->data; q->data=p->data; p->data=t; } q=q->next; p=p->next; } } return L; } ListNode Union_up(ListNode L1,ListNode L2,int k1,int k2) { ListNode p=L1->next,q=L2->next; L1->next=NULL; ListNode m=L1; while(k1>0&&k2>0) { if(p->data<q->data) { m->next=p; m=p; p=p->next; --k1; } else if(p->data==q->data) { m->next=p; m=p; p=p->next; q=q->next; --k1; --k2; } else { m->next=q; m=q; q=q->next; --k2; } } if(k1>0) { while(k1--) { m->next=p; m=p; p=p->next; } } else { while(k2--) { m->next=q; m=q; q=q->next; } } m->next=NULL; return L1; } ListNode swap(ListNode L,int k) { ListNode p,q,r=L; int n=int(k/2); for(int i=0;i<n;i++) { p=r->next; q=r->next->next; p->next=q->next; r->next=q; q->next=p; r=r->next->next; } return L; } ListNode union_2(ListNode L1,ListNode L2,int k1,int k2) { ListNode p=L1->next,q=L2->next,C; C=(ListNode)malloc(sizeof(Lnode)); C->next=NULL; ListNode m=C; while(k1>0&&k2>0) { if(p->data==q->data) { m->next=p; m=p; p=p->next; q=q->next; --k1; --k2; } else if(p->data<q->data) { p=p->next; k1--; } else { q=q->next; k2--; } } m->next=NULL; return L1; } ListNode del_abs_same(ListNode L,int k1) { ListNode p=L->next,q=L; int a[100]={0}; while(p!=NULL) { a[abs(p->data)]=1; p=p->next; } p=L->next; while(k1--) { if(a[abs(p->data)]==1) { a[abs(p->data)]=0; p=p->next; q=q->next; } else { q->next=p->next; p=p->next; } } return L; } ListNode union_set(ListNode L1,ListNode L2,int k1,int k2) { ListNode p=L1->next,q=L2->next; L1->next=NULL; ListNode m=L1; while(k1>0&&k2>0) { if(p->data<q->data) { m->next=p; m=p; p=p->next; --k1; } else if(p->data>q->data) { q=q->next; --k2; } else { p=p->next; q=q->next; --k1; --k2; } } while(k1) { m->next=p; m=p; p=p->next; --k1; } m->next=NULL; return L1; } ListNode create_tail(ListNode &L) { L=(ListNode)malloc(sizeof(Lnode)); L->next=NULL; int x; scanf("%d",&x); ListNode r=L,p; while(x!=99) { p=(ListNode)malloc(sizeof(Lnode)); p->data=x; p->next=r->next; r->next=p; scanf("%d",&x); } return L; } ListNode reserve(ListNode &L) { ListNode p=L->next,r; L->next=NULL; while(p!=NULL) { r=p; p=p->next; r->next=L->next; L->next=r; } return L; } ListNode add(ListNode &L,int value) { ListNode p=L->next,s; s=(ListNode)malloc(sizeof(Lnode)); s->data=value; while(p->next!=NULL) { p=p->next; } p->next=s; p=s; p->next=NULL; return L; } int length(ListNode L) { ListNode p=L->next; int len=1; while(p->next!=NULL) { len++; p=p->next; } return len; } void out(ListNode L) { ListNode p=L->next; while(p!=NULL) { printf("%d\n",p->data); p=p->next; } } ListNode insert(ListNode &L,int i,int value) { ListNode p=L,s; i=i-1; while (i&&p!=NULL) { p=p->next; i--; } s=(ListNode)malloc(sizeof(Lnode)); s->data=value; s->next=p->next; p->next=s; return L; } ListNode del_range(ListNode &L,int mink,int maxk) { ListNode p=L,q=L->next; while(q!=NULL) { if(q->data>=mink&&q->data<=maxk) { p->next=q->next; q=q->next; } else { q=q->next; p=p->next; } } p->next=NULL; return L; } ListNode del(ListNode &L,int i) { ListNode p=L,q=L->next; while(i-1) { i--; q=q->next; p=p->next; } p->next=q->next; free(q); return L; } void out_re(ListNode L) { if(L->next!=NULL) out_re (L->next); printf("%d",L->data); } void out_re_k(ListNode L,int k) { int le=length(L); ListNode p=L->next; le=le-k; while(le--) { p=p->next; } printf("%d",p->data); } //int main() //{ // ListNode L1,L2; // printf("输入第一个链表:"); // L1=create(L1); // printf("请输入第一个链表:"); // L2=create(L2); // L1=Union(L1,L2); // // out(L1); // //} // int main() // { // ListNode L1,L2; // printf("输入二个链表的长度"); // int k1,k2; // scanf("%d",&k1); // scanf("%d",&k2); // printf("请输入第一个链表:"); // L1=create_2(L1,k1); // printf("请输入第二个链表:"); // L2=create_2(L2,k2); // L1=union_set(L1,L2,k1,k2); // out(L1); // } int main() { ListNode L; L=create_2(L,5); L=up_sort(L,5); out(L); }在这里插入代码片
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。