学链表也学了有一段时间了,在这里先总结一下

1.链表的中头结点相当重要,判断是否有值或为空相当重要,建议头结点一般设置为不赋值

2.每次操作一般都是从移动元素的上一个结点来操作,这也是头结点为建议不赋值的原因

3.链表的每次指向变化最好还是画图更加清晰易懂

删除两条链表重复的数
我的思路就是用较长链表遍历较短链表,再创一条链表把不重复的数存储起来。。。#include <stdio.h>
#include<stdlib.h>
typedef struct node
{int data;struct node *next;
}NODE;
NODE *createa()
{NODE *head,*p,*q;int i,j,k;k=0;head=NULL;for(i=0;i<10;i++){p=(NODE *)malloc(sizeof(NODE));p->data=k+2;p->next=NULL;if(head==NULL){head=p;}else{q->next=p;}q=p;k+=2;}return head;
}
NODE *createb()
{NODE *head,*p,*q,*t;int i,j,k;k=0;head=NULL;for(i=0;i<5;i++){p=(NODE *)malloc(sizeof(NODE));p->data=k+2;p->next=NULL;if(head==NULL){head=p;}else{q->next=p;}q=p;k+=4;}return head;
}
void shuchu(NODE *head)
{while(head!=NULL){printf("%d ",head->data);head=head->next;}
}
NODE *shanchu(NODE* la,NODE *lb)//这篇代码的核心
{NODE *q,*p,*t,*head;int i,flag;q=la;p=lb;head=(NODE *)malloc(sizeof(NODE));//为下面存储不同数做准备 head->next=NULL;for(i=0;i<10;i++){   flag=0;while(p!=NULL){if(q->data==p->data)//较长链遍历较短链 {flag=1;break;}p=p->next;}if(flag==0){t=(NODE *)malloc(sizeof(NODE));//头插法创建新链存储不重复数 t->data=q->data;t->next=head->next;head->next=t;}q=q->next;// 判断下一个结点 p=lb;//新的遍历还是从较短链开始 }return t;//注意不要返回head;
}
int main(void)
{NODE *la,*lb,*q;la=createa();lb=createb();shuchu(la);printf("\n");shuchu(lb);printf("\n");q=shanchu(la,lb);while(q!=NULL){printf("%d ",q->data);q=q->next;}
}
冒泡排序//交换结点
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{int data;struct node *next;
}NODE;
NODE *create(int n)
{int a;NODE *head,*p,*q,*t;t=(NODE *)malloc(sizeof(NODE));head=NULL;while(n--){scanf("%d",&a);p=(NODE *)malloc(sizeof(NODE));p->data=a;p->next=NULL;if(head==NULL){head=p;}else{q->next=p;}q=p;}t->next=head;//设立一个空的表头,为下面结点交换做准备return t;
}
int paixu(NODE *head)//设链表为2,1,5,3,4
{NODE *pre,*p,*tail;  tail=NULL;  pre=head;  while((head->next)!=tail)   {  p=head->next;  pre=head;  while(p->next!=tail)  {  if((p->data)<(p->next->data))  {  pre->next=p->next; //pre->next=1...p->next = p->next->next;// p->next=5;确定了后面三个结点的连接pre->next->next = p; //pre->next->next=2;p = pre->next;  //p=1;}  //则pre->1,2,5,3,4,p->1,2,5,3,4,p=p->next;     pre=pre->next;     }  tail=p;  }  return 0 ;
}
int main(void)
{int n;NODE *p,*q,*t;scanf("%d",&n);p=create(n);paixu(p);while(p->next!=NULL){printf("%d ",p->next->data);p=p->next;}return 0;
}
头指针不变,后面的结点进行交换,需要注意的是除了两个比较的数之外后面结点的正确连接。。。
链表的逆置
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
struct node
{int data;struct node *next;
};
struct node *create(int count)
{struct node *phead,*pend,*pnew;int i;phead=pend=(struct node *)malloc(sizeof(struct node));/ srand((unsigned)time(NULL));for(i=0;i<count;i++){pnew=(struct node *)malloc(sizeof(struct node));pnew->data=rand()%100;pend->next=pnew;pend=pnew;}pnew->next=NULL;return phead;
}
void output(struct node * phead)
{phead=phead->next;//为什么要指向下一个呢?因为phead->pend;此时Pend为空, while(phead)//相当于b=a;a=3;无论a后来怎么变,b总等于最初的a。。。。 {printf("%d ",phead->data);phead=phead->next;}printf("\n");
}
void contrary(struct node *phead)
{struct node *ptemp1=phead->next,*ptemp2=phead->next;phead->next=NULL;while(ptemp2)//以下代码分成两部分来看 {ptemp1=ptemp2;//p2永远指向p1的下一个 ptemp2=ptemp1->next;ptemp1->next=phead->next;//妥妥的头插法啊 phead->next=ptemp1;}
}
int main(void)
{struct node *phead;int count=10;phead=create(count);output(phead);contrary(phead);output(phead);
} 
将两个有序链表合并再进行逆置
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
struct node
{int data;struct node *next;
};
struct node *create(int icount,int num)
{struct node *phead=NULL,*pend,*pnew;int i,j;phead=pend=(struct node*)malloc(sizeof(struct node));for(i=0,j=0;i<icount;i++){pnew=(struct node *)malloc(sizeof(struct node));pnew->data=j;j+=num;pend->next=pnew;pend=pnew;} pnew->next=NULL;return phead;
}
void output(struct node *phead)
{phead=phead->next;while(phead){printf("%-5d",phead->data);phead=phead->next;}printf("\n");
}
void merge(struct node *phead_a,struct node *phead_b)
{struct node *la,*lb,*lc,*la_t,*lb_t;//a指向la当前结点,b指向lb当前结点 la=phead_a->next;//la_t,lb_t可看作链表的备份 lb=phead_b->next;phead_a->next=NULL;while(la&&lb){if((la->data)<(lb->data)){//备份移动 la_t=la->next;//la_t备份比较数的下一个结点//头插法 la->next=phead_a->next;phead_a->next=la;//跟前面链表的逆置一样、、 la=la_t;//a移动到下一个结点 }else{ lb_t=lb->next;lb->next=phead_a->next;phead_a->next=lb;lb=lb_t;}}while(la)//接下来思路都跟上面一样,只是将较长链再头插进去而已 {la_t=la->next;la->next=phead_a->next;phead_a->next=la;la=la_t;}while(lb){lb_t=lb->next;lb->next=phead_a->next;phead_a->next=lb;lb=lb_t;}
}
int main(void)
{struct node *phead_a,*phead_b;srand((unsigned)time(NULL));int icount_a=rand()%20+1,icount_b=rand()%20+1;int a=rand()%4+1,b=rand()%4+1;phead_a=create(icount_a,a);phead_b=create(icount_b,b);output(phead_a);output(phead_b);merge(phead_a,phead_b);output(phead_a);return 0;
}
链表的交叉合并
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
struct node
{int data;struct node *next;
};
struct node*create(int icount)
{struct node *phead,*pend,*pnew;int i;pend=phead=(struct node*)malloc(sizeof(struct node));for(i=0;i<icount;i++){pnew=(struct node*)malloc(sizeof(struct node));pnew->data=rand()%100;pend->next=pnew;//尾插法 pend=pnew;}pnew->next=NULL;return phead;
}
void output(struct node *phead)
{phead=phead->next;while(phead){printf("%d ",phead->data);phead=phead->next;}printf("\n");
}
void merge(struct node *phead_x,struct node *phead_y)
{struct node *lx,*lx_h,*ly,*lz;lx=phead_x->next;ly=phead_y->next;lz=phead_x; while(lx)//lx短链表,ly长链表,lz指向已排好序链表的尾部 {                                           //会不会感到很奇怪为什么直接输出phead_x就可以,答案应该就是下一句lz=phead_x lz->next=lx;//连接lz和短链表的当前节点     //则lz->next=phead_x->next,接下来的操作都可以看作phead_x已经作为头节点 lx_h=lx->next;//备份lx的指针域 lx->next=ly;//连接lx当前节点和ly当前节点 lz=ly;//移动lz,使lz成为当前已排好节点尾部 lx=lx_h;//移动lx,使lx成为短链表未排好序的第一个 ly=ly->next;//移动ly,使ly成为长链表未排好序的第一个 }lz->next=ly;//连接剩下的长链表
}
int main(void)
{struct node *phead_a,*phead_b;srand((unsigned)time(NULL));int icount_a=rand()%20+1,icount_b=rand()%20+1;phead_a=create(icount_a);phead_b=create(icount_b);output(phead_a);output(phead_b);if(icount_a<=icount_b){merge(phead_a,phead_b);output(phead_a);free(phead_b);}else{merge(phead_b,phead_a);output(phead_b);free(phead_a);}
}
循环单链表的创建//尾节点指向头节点时退出
#include<stdio.h>
#include<stdlib.h>
typedef struct n{int data;struct n *next;
}node;
node *create(int count)
{int i;node *phead,*q,*p;phead=(node *)malloc(sizeof(node));q=phead;for(i=0;i<count;i++){p=(node *)malloc(sizeof(node));scanf("%d",&p->data);phead->next=p;phead=p;}phead=q;// head恢复开始时的位置 p->next=phead;//尾节点指向头节点 return phead;
}
void output(node *head){node *pt;pt=head->next;//head本身没有赋值 while(pt!=head)//当尾节点走到头节点时退出循环 {printf("%d ",pt->data);pt=pt->next;}
}
int main(void){int count;node *head;scanf("%d",&count);head=create(count);output(head);
}
双向单链表的创建//插入//删除
#include<stdio.h>//不难理解,建议画图所谓的删除与添加只是多考虑了一个指针域而已
#include<stdlib.h>
typedef struct n
{int data;struct n *pre,*next;
}node;
node *create(int count)
{int i;node *phead,*p,*q;phead=(node *)malloc(sizeof(node));q=phead;//phead数据域未给赋值 for(i=0;i<count;i++){p=(node *)malloc(sizeof(node));printf("输入数据:\n");scanf("%d",&p->data);p->pre=phead;//其实就是尾插法加上这个 phead->next=p;phead=p;}p->next=q;//完成头尾节点的互相指向 phead=q;phead->pre=p;return phead;
}
void output(node *head)
{node *p,*s;p=head->next;while(p!=head)//从左至右 {printf("%d ",p->data);p=p->next;}s=head->pre;printf("\n");while(s!=head)//从右至左 {printf("%d ",s->data);s=s->pre;}printf("\n");
}
void charu(node *head,int n)//链表的插入
{int i;node *p,*q,*s;p=head; for(i=1;i<n;i++)//i=1 {p=p->next;}s=(node *)malloc(sizeof(node));printf("输入待插入数:\n"); scanf("%d",&s->data);s->next=p->next;p->next=s;s->pre=p;(s->next)->pre=s;output(head);
}
void shanchu(node *head,int n)
{int i;node *p;p=head; for(i=0;i<n;i++)//注意这里和删除的不同 i=0 {p=p->next;}(p->next)->pre=p->pre;(p->pre)->next=p->next;output(head);free(p);
}
int main(void)
{int n;node *head;printf("请输入链表数\n");scanf("%d",&n);head=create(n);output(head);printf("输入待插入节点位置:\n");scanf("%d",&n);charu(head,n);printf("输入待删除节点位置:\n");scanf("%d",&n);shanchu(head,n);
}

链表学到这里再将前面的知识再过了一遍,多了一些该注意的点

struct node* shanchu(struct node *head)//链表的删除//没什么难度,就是得注意下循环中的break;
{//可以尝试下取掉break删除最后一个数就懂了int a;scanf("%d",&a);struct node *begin,*end,*p;begin=(struct node *)malloc(sizeof(struct node));begin=head;while(head->next!=NULL){if(a==head->next->data){p=(struct node *)malloc(sizeof(struct node));p=head->next->next;head->next=p;break;//}head=head->next;}
void paixu(struct node *head)//冒泡排序节点交换核心
{//基本没什么问题struct node *begin,*end,*pre,*p;end=NULL;while(head->next!=end)//设计的很巧妙{begin=head->next;pre=head;while(begin->next!=end){if(begin->data<begin->next->data){pre->next=begin->next;begin->next=begin->next->next;pre->next->next=begin;begin=pre->next;//这个东西不能忘,相当于后退一步再前进一步}begin=begin->next;pre=pre->next;}end=begin;}
}
void nizhi(struct node *head)//链表的逆置,,这之间的逻辑关系还是有点没理清
{struct node *begin,*end;begin=head->next;end=head->next;head->next=NULL;while(end){begin=end;end=begin->next;begin->next=head->next;head->next=begin;  }}
void shanchu(qnode *p1,qnode *p2)//链表的交叉合并
{qnode *la,*lb,*la_t,*lc;la=p1->next;lb=p2->next;lc=p1;while(la){lc->next=la;la_t=la->next;la->next=lb;//我写的是lc=lc->next;lc->next=lb,明显错了 lc=lb;//上面已经有lc->next=la,则la->next=lb可看成lc-la-lb la=la_t;lb=lb->next;}lc->next=lb;
}

链表学到这里就先告一段落,接下来会继续深入的

链表的基本应用二及总结相关推荐

  1. c语言 动态链表,C语言的链表(篇章之二:动态链表)

    一.[链表的创建]: [1].空链表: Node *createList() { Node *head = (Node*)malloc(sizeof(Node)); head->next = N ...

  2. 【开200数组解决二叉搜索树的建立、遍历】PAT-L3-016. 二叉搜索树的结构——不用链表来搞定二叉搜索树...

    L3-016. 二叉搜索树的结构 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值:若它的右子树不空,则右子树上所有结点的值均大于它 ...

  3. 就地链表反转_数据结构与算法系列之链表操作全集(二)(GO)

    以下完整的代码,及测试代码均可从这里获取 https://github.com/Rain-Life/data-struct-by-go 常见的链表操作 单链表反转 方法一:就地反转法 思路 就地反转法 ...

  4. java 单链表是否有环_数据结构与算法随笔之链表-链表是否有环(二)

    上一篇文章我们分析了下链表之反转单向链表,这篇文章我们来分析下另外一个关于链表的经典题目. 判断链表是否有环(在leetcode上的题目地址:环形链表) 题目描述 给定一个链表,判断链表中是否有环 解 ...

  5. 可由一个尾指针唯一确定的链表有_2013-2014学年二学期数据结构期末考试试卷(3卷)...

    题号 一 二 三 四 五 六 七 八 九 十 成绩 复核 得分 阅卷 题目部分, ( 卷面共有 35 题 ,100 分 , 各大题标有题量和总分 ) 一.应用题 (2 小题 , 共 16 分 ) 1 ...

  6. C++使用链表实现queue之二(附完整源码)

    C++使用链表实现queue 使用链表实现queue算法的完整源码(定义,实现,main函数测试) 使用链表实现queue算法的完整源码(定义,实现,main函数测试) #include <io ...

  7. 链表常见面试题二:约瑟夫环

    面试题1:约瑟夫环 约瑟夫环故事背景: 著名犹太历史学家 Josephus有过以下的故事: 在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中, 39个犹太人决定宁愿死也不 ...

  8. 大厂面试算法系列-如何实现链表的逆序(二)-递归法

    导语   接着上次的内容,上次博客中展示了原地进行单链表的逆序操作,当然除了原地逆序还可以通过递归的方式进行调用操作.下面就来看看通过递归的方式如何进行单链表的逆序操作. 递归法逆序链表   假定原来 ...

  9. 链表之单链表约瑟夫问题(二)

    约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出 ...

最新文章

  1. SFTP命令基本使用
  2. 基于GDI+用C#编写的.NET流程图控件开发周记(2011-08-28)
  3. SAP ABAP实用技巧介绍系列之利用RTTC给DDIC structure动态添加新的field
  4. extjs--combox用法
  5. typescript索引类型_typescript入门:高级类型
  6. csv文件python是怎么输入的,python怎么读取和写入csv文件
  7. 从Nginx、Apache工作原理看为什么Nginx比Apache高效!
  8. unzip直接覆盖解压
  9. 2021-08-13servlet 原理及注意事项
  10. 2021-07-31mysql 登录退出
  11. JSON字符串,JSON对象的相互转换
  12. 2016年读书总结(一)
  13. 嵌入式 C 语言(上)
  14. Android 即时通讯
  15. Pytorch ——基础指北_零 [神经元和激活函数介绍]
  16. 对于互联网,谈谈自己浅薄的看法
  17. Python实现一键生成微信好友头像墙
  18. 电信增值短信平台软件模块清单(sp专用)
  19. Java8 stream流式表达式用法
  20. 百度网盘提速加速方法

热门文章

  1. 与小弟子交谈:引申的思考笔记[第一次编辑]
  2. 数据库索引如何工作?原理
  3. 容器资源可视化隔离的实现方法
  4. 排名前100的PHP函数及分析
  5. Dubbo思维导图知识点整理
  6. netty ByteBuf对象池和内存泄漏检测实现走读
  7. 收获,不止SQL优化——抓住SQL的本质--第九章
  8. machinery入门看这一篇(异步任务队列)
  9. PHP总结:几个陷阱
  10. php的Snoopy类