小牛成长记--链表学习

寒假已经过去了吗?       哎,快哭了快哭了快哭了


寒假刷了一下数据结构,由于时间问题,刷的比较快,说实话有很多知识点都没掌握,就像是上英语课一样,老师教你一遍单词,你只能说你知道这个单词了,却不能说你会了。我就是这样的害羞

首先说一下需掌握的链表知识点:1.结点的概念。

                                     2.单链表的建立:包括正序建表和逆序建表。

                                     3. 单链表结点的查找,插入,删除。

                                     4. 单链表的逆置,归并, 拆分


       今天我又看了一下链表(因为当时没刷完题,有些题还不能太熟练地敲出,这样是不可以的),我们的课本也不知道怎么了,刚介绍完几种内存分配方式,当然重点是动态内存分配,然后直接开讲单链表节点的基本操作,比如单链表结点的查找,插入,删除。 。。。我想说的是我当时只是对单链表的基本组成单元--节点有了初步认识,对单链表都没有个整体概念,这可让我怎么学啊。所以第一次直接跪了。看的我雨里雾里的,好在一不小心往后翻书的时候看到了单链表的建立,顿时泪奔可怜,然后就把单链表的头插法和尾插法给收了,为我所用,我此时又多了一项技能。真不好意思害羞。  

     然后再返回来继续攻克单聊表的应用,时间不等人啊,此时已经过去了一上午和一下午,晚上还有任务--刷题,不过不怕,因为我觉得刷10道题,不如把一个知识点完全掌握,顿时我又来了激情。继续奋战。既然说到这了,我想你可能总结了一下学习单链表的顺序吧,哈哈,看来我猜对了。  首先对结点要了解,然后从基本组成单元到整体,也就是从结点到单链表,现在可能你非常好奇如何建立单链表吧,那就学习如何建立单链表吧。

建立单链表有两种方法:1.逆序建立单链表(头插法); 2.顺序建立单链表(尾插法); 

首先先讲一下顺序建表:1.首先建立一个头结点(不理解可以google一下)。2.然后就是开始建表了,现贴代码讲一下:

代码(顺序建立链表):

 struct node *head, *tail, *p;//定义结构体类型的指针变量head,tail,p,其中tail充当游动指针
    head = (struct node*)malloc(sizeof(struct node));//建立空节点,不放数据,只存放第一个节点的地址
    head->next = NULL;//指空
    tail = head;//头指针和尾指针开始时都指向head
    for(i=1; i<=n; ++i)//假设要建立n个节点,所以循环n次
    {
        //接下来为尾插法的核心代码
        p = (struct node *)malloc(sizeof(struct node));//申请内存,共申请n次
        scanf("%d", &p->data);//每申请一个结点,往里输入一个数据
        p->next = NULL;
        tail->next = p;//连接新申请的结点
        tail = p;//使tail指针往后移动一位
    }
再讲一下逆序建立链表:步骤和顺序建表差不多,只须改下核心代码即可:

代码:

struct node *head,  *p;//定义结构体类型的指针变量head,p,其中p充当游动指针
    head = (struct node*)malloc(sizeof(struct node));//建立空节点,不放数据,只存放第一个节点的地址
    head->next = NULL;//使头结点指空
    for(i=1; i<=n; ++i)//假设要建立n个节点,所以循环n次
    {
        //接下来为头插法的核心代码
        p = (struct node *)malloc(sizeof(struct node));//申请内存,共申请n次
        scanf("%d", &p->data);//每申请一个结点,往里输入一个数据
        p->next = head->next;//把头结点后的第一个结点的地址赋给p(注意:当第一次循环时,head->next 指向NULL
        //此时p指针指向为空),则p指向头结点的下一个结点。
        head->next = p;//使p结点连在head结点后。
    }


建立完后,你又想了,我建单链表到底有什么用啊,这时你碰巧发现了单链表的应用。

         你此时是不是忽然想起了数组,。。。对。。。,我记得在数组中可以查找,删除,或插入某个值,那么在链表中可不可以呢?

答案是肯定的,而且比用数组更简洁。

      1.查找
           首先来看一下如何在链表中查找某个值是否存在吧,核心代码:

       

struct node 
{
    int data;
    struct node *next;
};
struct node *search(struct node *head, int key)
{
    struct node *p;//p为游动指针
    p = head->next;游动指针指向第一个实际结点
    while(p!=NULL)
    {
        if(p->data==key)
            return(p);//找到,返回该节点的地址
        else
            p = p->next;//未找到,指向下一个结点继续查找
    }    
    return NULL;//循环正常结束,说明不存在该节点
}

查找是不是很简单啊,就像在数组中查找某元素是否存在一样。在数组中是借助下标来遍历整个数组,而在单链表中是借组指针(next 指针)来遍历。现在你应该掌握了单链表的查找吧,不要着急,接下来你就要学习单链表的插入了,在讲之前,首先回忆一下,怎么往数组中插入一个元素呢?疑问,其实往数组中也是可以插入某个元素的,但是比较麻烦,有兴趣的同学可以自己写一下,那么有没有更简单的方法呢?

  当然有了,那就是用链表代替数组,往单链表中插入元素就会很简单了。接下了就讲讲如何往单链表中插入元素。

2.插入

     思路:假如现在需往1, 2两个结点中插入3结点,那么只需把第一结点中存放的地址赋给3,然后再把第三个结点的地址赋给第一个结点即可。

     是不是很简单啊微笑

      核心代码:

void insert(struct node *head, int key)
{
    struct node *q;
    q = (struct node *)malloc(sizeof(struct node));
    if(!q)
    {
        printf("不能分配内存空间!");
        exit(0);
    }
    q->data = key;//在p结点后插入q结点
    q->next = NULL;
    q->next = p->next;
    p->next = q; 
}
现在你已经知道了如何往单链表中查找结点,如何插入结点,还有就是如何删除某个结点呢?微笑

  3.删除

     思路:假如现在需在1, 3两个结点中删除2结点,那么只需把第3个结点的地址赋给1,然后再把第2个结点的释放(free())即可。

  核心代码:

//此函数为删除带头结点的单链表中第一个值为key的结点的函数
int del(struct node *head, int key)
{
    struct node *p, *q;
    int flag = 0;
    p = head;
    while(p->next!=NULL)
    {
        if(p->next->data==key)
        {
            flag = 1;
            break;
        }
        else
            p = p->next;
    }
        if(flag==1)
        {
            q = p->next;
            p->next = q->next;
            free(q);
            return 1;
        }
        else
            return 0;
    }

以上就是对单链表的基础操作,现在是不是很高兴啊,你已经掌握了单链表的基础知识了,接下来你会发现,这些基本操作是多么的重要;


接下来就应该更上一层了.奋斗,你做好准备了吗?

由于课程太紧,所以只能分几次写了委屈

。。。。。。。。。。。。。。。。。。。。未完完未未完。。。。。。。。。。。。

 










     

posted @ 2014-03-05 20:31  6bing  阅读(200)  评论(0编辑  收藏  举报