单链表操作创建、添加节点、排序

链表基本结构示意图

1.链表与结构体数组的区别

链表的添加节点是通过malloc函数分配内存的,也就是他的地址可以是不连续的。

而数组是一次性分配一段内存,后期不可以更改大小。

由上对比分析,链表的优点有可以灵活控制大小,在不确定对象元素个数的情况下使用链表存储对象元素信息是一种不错的解决方案,应为用静态数组难免会照成内存浪费(对象元素少于数组个数),更严重的会导致数组下标溢出(对象元素多于数组个数)。

但是链表也有缺点。因为新的节点要通过malloc函数分配内存。由于内存对齐的机制,多次使用malloc函数势必造成内存的碎片化,也会让费内存。

2.链表的基本结构


基本元素

链表最基本的单元是一个结构体变量,且成员变量中至少要有一个指向自身类型的结构体指针。其余可以有任意多个成员变量来描述对象元素的各种信息,类如一个学士信息的结构体中成员变量可以有学号、成绩、性别等等。

一般链表由一个头节点和若干个成员节点构成,头节点就用作索引整个链表,你可以通过头节点中的指针,顺藤摸瓜遍历出链表的所有的成员变量。

3.链表的创建


链表创建

所谓创建链表就是创建一个head节点,并且初始化各项信息。一般而言头节点不用来存储信息,只用作索引。所以初始化时只需要将成员变量中的指针初始化为NULL即可。

4.链表元素添加

链表元素添加大致分为三种:1.头部添加、2.尾部添加、3.指定位置添加

这里暂时只讨论前两种,指定位置添加等有时间再写。

头部添加顾名思义就是把新的节点插入到链表的开头,当然,还是要维护head节点的大佬地位,也就是新的节点要插入到紧随head 节点的下一个位置。


头部插入节点


操作示意图

如图所示要想在头部添加一个节点,要有两个步骤,断开头节点与原先第一个节点的联系,然后再把新节点指向原先的第一个节点是不是又构成一个完整链表了。

这里有一个很重要的注意点:每个节点中的指针变量都很重要,因为它是索引到下一个节点唯一途径,若是丢失了,那就无论如何也找不到下一个节点的信息了。就像茫茫人海中你要找一个人,却把他的手机号弄丢了。就联系不上了。

所以执行上图第一步操作时,记得保留好头节点里的指针值,或者直接先赋值给G节点中的指针变量,方法有很多,原则是不能丢失指针的值。

6.链表排序

链表的排序有两种方式:换值和换位置

换值较为简单,找出需要交换的两个节点,利用中间变量将它们中除了指向下一节点的指针变量以外的值都交换了。

而换位置较为复杂,需要更改链表节点的链接指针方式,要考虑地方较多。直接上代码。

//这是选择排序  特点有效值上浮

//形参 链表头节点

void select_sort_swap_num(info_stu*head)

{    

        info_stu *i,*j;     //链表结构体 

        int temp;    

        i = j = head->p_next;    //指向第一个有效节点

        if(head->p_next != NULL)    //确定有大于1个有效节点

        {        

                while(i != NULL)       

              {            

                    j=i->p_next;            

                    while (j != NULL)           //选择排序  有效值上浮

                   {               

                      if(j->xuehao < i->xuehao)               

                    {                   

                         temp = j->xuehao;                  //换值 

                         j->xuehao = i->xuehao;                    

                         i->xuehao = temp;               

                 }               

                 j = j->p_next;            

            }                       

             i = i->p_next;                   

         }    

    }

}


以上的换值排序较为简单,以下由两种方式实现的换位置排序法分别是冒泡排序和选择排序。

相比较而言,冒泡排序较为简易,因为涉及换位置的两个节点总是相邻的。而选择排序涉及的两个节点可能不相邻,换位置的方式是不太一样的。个人见解,或许有好的方法把它们统一起来,欢迎指导。

//这是选择排序

void select_sort_swap_address(info_stu*head)

{

    //分别要记录下来ij节点的前后节点信息。

    info_stu *i,*j,*i_pre,*i_next,*j_pre,*j_next,*temp;    //相邻交换  非相邻交换    

    i = j = head->p_next;   

    i_next = j_next = head->p_next->p_next;    

    i_pre = j_pre = head;    

    if(head->p_next != NULL)    

    {       

        while(i != NULL)        

        {            

            j=i->p_next;

            //            print_list(head);            

            while (j != NULL)           

            {                

                if(j->xuehao > i->xuehao)                

                {                     

                    //先上下文保存                   

                     i_next = i->p_next;                   

                     j_next = j->p_next;                    

                    if(j == i->p_next)  //side by side                   

                     {                                               

                        i_pre->p_next = j;                       

                         i->p_next = j_next;                       

                         j->p_next = i;             //i 和 j也要恢复      至关重要我被这个坑了        

                        i = i_pre->p_next;                       

                         j = i->p_next;                   

                     }                    

                    else                   

                     {                       

                         i_pre->p_next = j;                       

                         j_pre->p_next = i;                       

                         i->p_next = j_next;                       

                         j->p_next = i_next;                       

                         i = i_pre->p_next;     //恢复ij位置                  

                         j = j_pre->p_next;                   

                     }               

                 }               

                 j_pre = j;                

                j = j->p_next;            

            }            

             i_pre = i;                      

             i = i->p_next;                   

         }   

     }

}    

以上最重要的就是恢复ij位置的问题了。如图演示:


交换节点大致流程

画图好麻烦,如果需要交换的是相邻位置的节点,又有点不同但大致思想相同,且也必须注意恢复IJ的位置。

最后附上冒泡排序的代码,注意点就是更新tail节点,因为冒泡法有效值是下沉的。

void BubbleSort2(info_stu* head){    

    info_stu *p,*q,*tail,*q_pre;    

    tail = NULL;    

    p = head->p_next;    

    q_pre = p;    

    q = p->p_next;    

    while (head->p_next->p_next != tail)    

    {        

        q = head->p_next;        

        q_pre = head;        

        while(q->p_next != tail)        

        {           

             if((q->xuehao) < (q->p_next->xuehao))           

             {                

                q_pre->p_next = q->p_next;                

                q->p_next = q->p_next->p_next;                

                q_pre->p_next->p_next = q;  //交换完成 要恢复变量q******                

                q = q_pre->p_next;            

            }            

            q_pre = q;            

            q = q->p_next;       

         }        

        tail = q;    

    }    

}

脑阔疼,代码都要自己按空格对齐一下。。。。。

希望对阅读者有所帮助。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349