链表的基本操作之插入、删除、逆置
2016-05-29 15:48
281 查看
上一篇写了有关链表的创建和遍历等相关内容,今天就来讲讲有关链表的其他操作吧。
提到链表,无非就是指针指来指去,最终连成一个链。好多人困惑的地方就在于p->next=r->next,指针到底是如何指向的,弄清楚这个,删、查、排的操作也就很容易弄懂了。大家都知道‘=’是赋值运算符吧,它左边是变量,右边是常量,既然了解了这些,那么让我们回到p->next=r->next这个表达式上,p->next既然是变量,它表示p这个指针的next的指向,而r->next是常量,它代表的是r指针的next的指向的位置,综合一下左右两端,就是p这个指针的下一个指向是r指针的next的指向的位置。可能这样有点绕,但你画个图,结合这句话,相信你一定会懂得。
先来讲一下插入吧,前面不是创建链表时讲了头插和尾插法嘛,其实就是那样的思想,只不过这只是插一个元素,插完后就要将链表连起来,注意一定要先连接的是后面。插入分为三种,头插、尾插、在中间随机插。在这儿我们就以不带头结点的创建链表的方式为例吧,在这儿就只写插入的代码吧。
至于用头插法和尾插法创建的链表,我们就需要做点小小的改动,因为我们知道它们创建的链表的头结点都是空的,没有数据域,因此我们在对它们操作时,就要从head->next 开始,这样插入的头插法就有点变动了,有点类似在链表中插入,具体的可以自己试试,万一还是搞不定,可以留言哦!
现在我们来说说删除吧,删除我们要关心的两个方面是:一、数据重复,二、数据不存在,以前一直用循环遍历链表,当它是否和要删除的结点一致,这样我们就忽略了这两点,当你不知道链表的数据时,如果用这样的删除方式,后果很严重的哦!现在就来看看删除的代码.
接下来就来说说逆置的操作吧,之前一直强调只要弄明白链表的指针指向,这些问题都会迎刃而解的。逆置的操作就是我先将链表拆封开,将head和最后的NULL连接起来,然后通过一个循环一直在head前插入,每次将新插入的点定义为head,最后整个链表又会重新连接起来,成为一个逆置的链表。思路就是这样的,但是链表的创建方式不同,具体操作也会有点小的变动。以下代码就是根据带头结点的创建方式逆置的。
至于链表的排序,我也不知道具体该咋讲,都得靠自己对于链表的指针指向的正确理解。搞不懂的时候就得在纸上画出它的指向究竟是咋样的。这里就先给出选择排序的算法吧。
好了,今天就说这么多吧,可能我的理解也有错误,还需各位指正啊!
提到链表,无非就是指针指来指去,最终连成一个链。好多人困惑的地方就在于p->next=r->next,指针到底是如何指向的,弄清楚这个,删、查、排的操作也就很容易弄懂了。大家都知道‘=’是赋值运算符吧,它左边是变量,右边是常量,既然了解了这些,那么让我们回到p->next=r->next这个表达式上,p->next既然是变量,它表示p这个指针的next的指向,而r->next是常量,它代表的是r指针的next的指向的位置,综合一下左右两端,就是p这个指针的下一个指向是r指针的next的指向的位置。可能这样有点绕,但你画个图,结合这句话,相信你一定会懂得。
先来讲一下插入吧,前面不是创建链表时讲了头插和尾插法嘛,其实就是那样的思想,只不过这只是插一个元素,插完后就要将链表连起来,注意一定要先连接的是后面。插入分为三种,头插、尾插、在中间随机插。在这儿我们就以不带头结点的创建链表的方式为例吧,在这儿就只写插入的代码吧。
struct Node *Insert(struct Node *head)//头插法 { struct Node *p; p=(struct student *)malloc(sizeof(struct student)); scanf("%d",&p->date); p->next=head; head=p; return head; } struct Node *Insert(struct Node *head)//尾插法 { struct Node *p,*t=head; while(t&&t->next!=NULL){ t=t->next; } p=(struct student *)malloc(sizeof(struct student)); scanf("%d",&p->date); t->next=p; p->next=NULL; return head; } struct Node *Insert(struct Node *head,int Date)//在链表中插入 { struct Node *p,*t=head; while(t&&t->date!=Date){ t=t->next; } p=(struct student *)malloc(sizeof(struct student)); scanf("%d",&p->date); p->next=t->next; t->next=p; return head; }
至于用头插法和尾插法创建的链表,我们就需要做点小小的改动,因为我们知道它们创建的链表的头结点都是空的,没有数据域,因此我们在对它们操作时,就要从head->next 开始,这样插入的头插法就有点变动了,有点类似在链表中插入,具体的可以自己试试,万一还是搞不定,可以留言哦!
现在我们来说说删除吧,删除我们要关心的两个方面是:一、数据重复,二、数据不存在,以前一直用循环遍历链表,当它是否和要删除的结点一致,这样我们就忽略了这两点,当你不知道链表的数据时,如果用这样的删除方式,后果很严重的哦!现在就来看看删除的代码.
Linklist *delect(Linklist *h,int m) { Linklist *p=h,*t; while(p->next!=NULL){ if(p->date != m){ t=p; p=p->next; } else{ t->next=p->next; p=t->next; } } return h; }
接下来就来说说逆置的操作吧,之前一直强调只要弄明白链表的指针指向,这些问题都会迎刃而解的。逆置的操作就是我先将链表拆封开,将head和最后的NULL连接起来,然后通过一个循环一直在head前插入,每次将新插入的点定义为head,最后整个链表又会重新连接起来,成为一个逆置的链表。思路就是这样的,但是链表的创建方式不同,具体操作也会有点小的变动。以下代码就是根据带头结点的创建方式逆置的。
struct Node *reserve(struct Node *h) { struct Node *p,*t; p=h->next; t=p->next; p->next=NULL; while(t!=NULL){ p=t->next; t->next=h->next; h->next=t; t=p; } return h; }
至于链表的排序,我也不知道具体该咋讲,都得靠自己对于链表的指针指向的正确理解。搞不懂的时候就得在纸上画出它的指向究竟是咋样的。这里就先给出选择排序的算法吧。
Linklist *sort(Linklist *head)/*选择排序*/ { Linklist *temp1,*temp2,*q,*p; for(q=head;q->next!=NULL;q=q->next) for(p=q->next;p->next!=NULL;p=p->next) { if(p->next->data<q->next->data) if(q->next==p)//当他们是相邻结点的情况 { temp1=p->next; p->next=p->next->next; temp1->next=q->next; q->next=temp1; p=temp1; } else { temp1=p->next; temp2=q->next; p->next=p->next->next; q->next=q->next->next; temp1->next=q->next; q->next=temp1; temp2->next=p->next; p->next=temp2; } } return head; }
好了,今天就说这么多吧,可能我的理解也有错误,还需各位指正啊!
相关文章推荐
- [C/C++]反转链表
- 关于指针的一些事情
- C#实现基于链表的内存记事本实例
- C#模拟链表数据结构的实例解析
- C# Pointer指针应用实例简述
- C++智能指针实例详解
- C++指向函数的指针实例解析
- 关于c语言指针的两处小tip分享
- 浅析iterator与指针的区别
- 探讨C++中数组名与指针的用法比较分析
- C++编程指向成员的指针以及this指针的基本使用指南
- 详解C++中的指针、数组指针与函数指针
- C语言实现带头结点的链表的创建、查找、插入、删除操作
- C++中字符串以及数组和指针的互相使用讲解
- C语言安全之数组长度与指针实例解析
- C++中指向对象的常指针与指向常对象的指针详解
- 指向变量的常指针与指向常变量的指针详细解析
- C#通过指针实现快速拷贝的方法
- C++利用静态成员或类模板构建链表的方法讲解
- C++实现简单的学生管理系统