zoukankan      html  css  js  c++  java
  • C语言 链表的使用(链表的增删查改,链表逆转,链表排序)

    //链表的使用
    
    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    //定义链表结构体
    struct LinkCode{
        int num;
        char sname[50];
        struct LinkCode * linknext;
    };
    
    //静态链表
    void Linkone(){
        struct LinkCode n1, n2, n3, n4, n5;
        struct LinkCode * head = NULL;
        //初始化变量
        n1.num = 1;
        sprintf(n1.sname, "小明");
        n1.linknext = &n2;
    
        n2.num = 2;
        sprintf(n2.sname, "小红");
        n2.linknext = &n3;
    
        n3.num = 3;
        sprintf(n3.sname, "小芳");
        n3.linknext = &n4;
    
        n4.num = 4;
        sprintf(n4.sname, "小刚");
        n4.linknext = &n5;
    
        n5.num = 5;
        sprintf(n5.sname, "小志");
        n5.linknext = NULL;
    
        printf("
    ==========静态链表============
    ");
    
        //循环遍历----查询
        printf("
    ==========查询============
    ");
        for (head = &n1; head!= NULL; head = head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
    
        //增加
        printf("
    ==========增加============
    ");
        struct LinkCode n6;
        n6.num = 6;
        sprintf(n6.sname, "小雨");
    
        struct LinkCode n7;
        n7.num = 7;
        sprintf(n7.sname, "小丽");
    
        //情景1,插入末尾
        printf("
    ==========增加到末尾============
    ");
        n5.linknext = &n6;
        n6.linknext = NULL;
        //循环遍历----查询
        for (head = &n1; head != NULL; head = head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
        //情景2,插入到中间2后面
        printf("
    ==========增加到中间============
    ");
        struct LinkCode *px=NULL;
        for (head = &n1; head != NULL; head = head->linknext)
        {
            //注意for循环的执行顺序
            if (head->num==2)
            {
                px = head->linknext;
                head->linknext = &n7;
                n7.linknext = px;
            }
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
        //修改
        printf("
    ==========修改============
    ");
        //把小红的num修改成99
        for (head = &n1; head != NULL; head = head->linknext)
        {
            //strcmp()函数  串比较 str1>str2,返回值 > 0;两串相等,返回0
            if (!strcmp(head->sname,"小红"))
            {
                head->num = 99;
            }
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
        //删除
        printf("
    ==========删除============
    ");
        //删除num是7的节点
        for (head = &n1; head != NULL; head = head->linknext)
        {
            if (head->num==7)
            {
                //找到该节点的地址,再次重新开始循环遍历
                px = head;
            }
        }
    
        for (head = &n1; head != NULL; head = head->linknext)
        {
            if (head->linknext==px)
            {
                //找到要删除节点的上一个节点
                head->linknext = px->linknext;
            }
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
    
        printf("
    ");
    }
    
    //动态链表
    void LinkTwo(){
        struct LinkCode * head, *p1, *p2, *p3, *p4, *p5;
        head = p1 = p2 = p3 = p4 = p5 = NULL;
        //先分配内存
        p1 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p2 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p3 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p4 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p5 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
    
        p1->num = 1;
        sprintf(p1->sname, "小明1");
        p1->linknext = p2;
    
        p2->num = 2;
        sprintf(p2->sname, "小红1");
        p2->linknext = p3;
    
        p3->num = 3;
        sprintf(p3->sname, "小芳1");
        p3->linknext = p4;
    
        p4->num = 4;
        sprintf(p4->sname, "小刚1");
        p4->linknext = p5;
    
        p5->num = 5;
        sprintf(p5->sname, "小志1");
        p5->linknext = NULL;
    
        printf("
    ==========查询============
    ");
        //循环打印
        for (head = p1; head != NULL; head=head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
        //增加
        printf("
    ==========增加============
    ");
    
        struct LinkCode *p6 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        struct LinkCode *p7 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
    
        p6->num = 6;
        sprintf(p6->sname, "小雨1");
        p6->linknext = NULL;
    
        p7->num = 7;
        sprintf(p7->sname, "小丽1");
        p7->linknext = NULL;
    
        //情景1,在末尾追加
        p5->linknext = p6;
        printf("
    ==========增加(在末尾追加)============
    ");
        //循环打印
        for (head = p1; head != NULL; head = head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
        printf("
    ==========增加(在中间追加)============
    ");
        struct LinkCode *py = NULL;
        //情景2,在中间追加(追加在小红后面)
        for (head = p1; head != NULL; head = head->linknext)
        {
            if (!strcmp(head->sname, "小红1"))
            {
                py = head->linknext;
                head->linknext = p7;
                p7->linknext = py;
            }
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
        //修改
        printf("
    ==========修改============
    ");
        p1->num = 99;
        for (head = p1; head != NULL; head = head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
        //删除
        printf("
    ==========删除============
    ");
        //删除节点num=4的节点
        for (head = p1; head != NULL; head = head->linknext)
        {
            if (head->num==4)
            {
                //找到要删除的节点
                py = head;
            }
        }
        for (head = p1; head != NULL; head = head->linknext)
        {
            if (head->linknext==py)
            {
                head->linknext = py->linknext;
                free(py);
                //注意:动态链表的删除和静态链表的删除不同,静态链表创建是在栈中,而动态链表是用malloc()函数创建
                //所以动态链表在堆中,想要删除必须程序员手动用free()函数删除
            }
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
        printf("
    ");
    }
    
    //链表销毁
    void ClearLink(){
        printf("
    ==========创建链表============
    ");
        struct LinkCode * head, *p1, *p2, *p3, *p4, *p5;
        head = p1 = p2 = p3 = p4 = p5 = NULL;
        //先分配内存
        p1 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p2 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p3 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p4 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p5 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
    
        p1->num = 1;
        sprintf(p1->sname, "小明1");
        p1->linknext = p2;
    
        p2->num = 2;
        sprintf(p2->sname, "小红1");
        p2->linknext = p3;
    
        p3->num = 3;
        sprintf(p3->sname, "小芳1");
        p3->linknext = p4;
    
        p4->num = 4;
        sprintf(p4->sname, "小刚1");
        p4->linknext = p5;
    
        p5->num = 5;
        sprintf(p5->sname, "小志1");
        p5->linknext = NULL;
    
        printf("
    ==========查询============
    ");
        //循环打印
        for (head = p1; head != NULL; head = head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
        //销毁链表(只要给我一个头结点的地址,我能够删除整个链表)
        printf("
    ==========销毁链表============
    ");
        //思路:一个个删除,保留第一个,删除第二个,把第三个重新连接成第二个
        struct LinkCode *pt = NULL;
        //循环打印
        while (p1->linknext!=NULL){
            //获取第二个的地址
            pt = p1->linknext;
            //把第三个的地址放到第一个后面
            p1->linknext = p1->linknext->linknext;
            //删除第二个
            free(pt);
        }
        //当p1->linknext!=NULL时,表示整个链表只剩下第一个了
        //循环打印
        for (head = p1; head != NULL; head = head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
        //此时再删除第一个
        free(head);
        printf("
    头结点的指针地址%x", head);
    }
    
    //链表逆转
    void sort(){
        printf("
    ==========创建链表============
    ");
        struct LinkCode * head, *p1, *p2, *p3, *p4, *p5;
        head = p1 = p2 = p3 = p4 = p5 = NULL;
        //先分配内存
        p1 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p2 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p3 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p4 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p5 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
    
        p1->num = 1;
        sprintf(p1->sname, "小明1");
        p1->linknext = p2;
    
        p2->num = 2;
        sprintf(p2->sname, "小红1");
        p2->linknext = p3;
    
        p3->num = 3;
        sprintf(p3->sname, "小芳1");
        p3->linknext = p4;
    
        p4->num = 4;
        sprintf(p4->sname, "小刚1");
        p4->linknext = p5;
    
        p5->num = 5;
        sprintf(p5->sname, "小志1");
        p5->linknext = NULL;
    
        printf("
    ==========查询============
    ");
        //循环打印
        for (head = p1; head != NULL; head = head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
        //链表逆转(只给头结点的地址)
        printf("
    ==========链表逆转============
    ");
        //思路;存储第一个的地址,让第一个的下一个是NULL,第二个的下一个是原来的第一个,第三个下一个是原来的第二个
        head = p1;
        struct LinkCode *px = head;//头结点
        struct LinkCode *py = head->linknext;//第二个节点
        struct LinkCode *pz = NULL;
        while (py!=NULL){
            pz = py->linknext;//第三个节点
            //开始逆转
            py->linknext = px;//将第二个节点的下个节点赋值为第一个节点的地址
            //开始将所有指针向前移动1位
            px = py;//将第一个节点向前移动1位(移动到第二个节点的位置)
            py = pz;//将第二个节点向前移动1位(移动到第三个节点的位置)
            //此时再次进入循环 pz = py->linknext;   这会将第三个节点的值变成第四个节点
            //当py->linknext==NULL(即pz =NULL)的时候;表明此时py已经是链表最后一个节点了,
            //那么py->linknext的值就必须是链表倒数第二个的地址,所以还需要再循环1次,给py->linknext赋值,
            //再次经过py = pz;此时py==NULL;
        }
        //这个时候原来的第一个节点的linknext属性的值还是第二个节点的地址,,这是错误的,应该置为空
        head->linknext = NULL;
        //此时px就是原来链表最后一个节点的地址,因为head必须是头结点并且链表已经逆转了,
        //所以head的值不能是原来的第一个节点,而应该是原来链表最后一个节点的地址
        head = px;
        //循环打印
        for (head; head != NULL; head = head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
    
    }
    
    //链表排序(方法1)
    //方法1:交换2个元素的位置
    //缺点:理解复杂,操作麻烦
    //链表的冒泡排序与数组有巨大区别
    //数组每个元素都可以单独确定,a[1]就是第二个元素
    //但是链表他的每个元素都是由他的上一个元素确定,不存在有多少个元素的概念,只是上一次可以找到下一个
    void Sort2(){
        printf("
    ==========创建链表============
    ");
        struct LinkCode * head, *p1, *p2, *p3, *p4, *p5;
        head = p1 = p2 = p3 = p4 = p5 = NULL;
        //先分配内存
        p1 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p2 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p3 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p4 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p5 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
    
        p1->num = 30;
        sprintf(p1->sname, "小明1");
        p1->linknext = p2;
    
        p2->num = 12;
        sprintf(p2->sname, "小红1");
        p2->linknext = p3;
    
        p3->num = 9;
        sprintf(p3->sname, "小芳1");
        p3->linknext = p4;
    
        p4->num = 4;
        sprintf(p4->sname, "小刚1");
        p4->linknext = p5;
    
        p5->num = 2;
        sprintf(p5->sname, "小志1");
        p5->linknext = NULL;
    
        printf("
    ==========查询============
    ");
        //循环打印
        for (head = p1; head != NULL; head = head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
        //链表排序(只给头结点的地址)---由小到大
        printf("
    ==========链表排序============
    ");
        //思路;定义3个变量,因为链表无法通过当前元素获取上一个元素,所以只能用一个变量将上一个变量的地址记录下来
    
        //px--代表第一个元素,py代表第二个元素,pz代表第三个元素
        //参与比较的是py与pz
        struct LinkCode * px, *py, *pz;
        //初始化指针,防止后面出错
        px = py = pz=NULL;
        //在比较链表前2个元素的时候,第一个元素没有上一个元素,所以px=py=head
        px =py= head=p1;
    
        
        //冒泡排序,每循环一次,会将一个最大值移动到末尾,每移动一次,需要移动的元素就会少一个
        //一共5个元素,移动4次后,最大的元素都已经放到链表末尾
        int index = 4;
        while (index){//外层循环
            //获取第三个元素的值
            pz = py->linknext;
            if (py->num>pz->num)
            {
                //如果第一个节点的num比第二个大,则要求交换位置
                //1.把第一个节点的下个节点属性赋值为第三个节点的地址
                //此时px是第一个元素
                px->linknext = pz;
                //2.把第二个节点的下个节点属性赋值为第四个节点的地址
                py->linknext = pz->linknext;
                //3.把第三个节点的下个节点属性赋值为第二个节点的地址
                pz->linknext = py;
                //第一组交换完成
                //4.将所有节点向前移动一位,这里px已经不是第一个元素了,他往前移动1位
                //因为要确定头结点的值,所以前2个元素的比较,必须单独提取出来
                head = px = pz;
            }
            do{
                pz = py->linknext;
                if (py->num>pz->num)
                {
                    //如果第一个节点比第二个大,则要求交换位置
                    //1.把第一个节点的下个节点属性赋值为第三个节点的地址
                    px->linknext = pz;
                    //2.把第二个节点的下个节点属性赋值为第四个节点的地址
                    py->linknext = pz->linknext;
                    //3.把第三个节点的下个节点属性赋值为第二个节点的地址
                    pz->linknext = py;
                    //第一组交换完成
                    //4.将所有节点向前移动一位
                    px = pz;
                }
                else{
                    //如果大小顺序正确,3个元素都需要再向前移动1位;
                    //把第二个元素赋值给原来第一个元素
                    px = py;
                    //把第三个元素赋值给原来第二个元素
                    py = pz;
                }
            } while (py->linknext != NULL);//判断第三个元素是否是空
            //再次初始化
            //因为此时px,py,pz都已经移动到链表末尾
            px = py = head;
            pz = py->linknext;
            index--;
        }
        
        
    
    
        //循环打印
        for (head; head != NULL; head = head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
    
    }
    
    //链表排序(方法2)
    //方法1:交换2个元素的内容,不改变链表节点的位置,只是内容的交换
    //优点:操作简单,通俗易懂
    void Sort3(){
        printf("
    ==========创建链表============
    ");
        struct LinkCode * head, *p1, *p2, *p3, *p4, *p5;
        head = p1 = p2 = p3 = p4 = p5 = NULL;
        //先分配内存
        p1 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p2 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p3 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p4 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
        p5 = (struct LinkCode *)malloc(sizeof(struct LinkCode));
    
        p1->num = 3;
        sprintf(p1->sname, "小明1");
        p1->linknext = p2;
    
        p2->num = 12;
        sprintf(p2->sname, "小红1");
        p2->linknext = p3;
    
        p3->num = 9;
        sprintf(p3->sname, "小芳1");
        p3->linknext = p4;
    
        p4->num = 4;
        sprintf(p4->sname, "小刚1");
        p4->linknext = p5;
    
        p5->num = 2;
        sprintf(p5->sname, "小志1");
        p5->linknext = NULL;
    
        printf("
    ==========查询============
    ");
        //循环打印
        for (head = p1; head != NULL; head = head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
        //链表排序(只给头结点的地址)---由小到大
        printf("
    ==========链表排序============
    ");
    
        struct LinkCode *px = NULL;
        struct LinkCode *py = NULL;
        struct LinkCode sz;
    
        for (px = head = p1; px != NULL; px = px->linknext)
        {
            for (py = head = p1; py != NULL; py = py->linknext)
            {
                //双循环
                //外循环的一个元素跟其他5个元素相比较,只要px<py就会发生交换
                //导致当2是最小元素的时候,他必须先跟前面比他大的所有元素,把自己变成最大,并非单单与最大元素进行交换
                //也就是小元素会不断的被推到最前面
                if (px->num<py->num)
                {
                    sz.num = px->num;
                    px->num = py->num;
                    py->num = sz.num;
    
                    sprintf(sz.sname, px->sname);
                    sprintf(px->sname, py->sname);
                    sprintf(py->sname, sz.sname);
                }
            }
        }
        //循环打印
        for (head = p1; head != NULL; head = head->linknext)
        {
            printf("
    num=%d,sname=%s,linknext=%x", head->num, head->sname, head->linknext);
        }
    
    }
    
    void main(){
        //Linkone();
        //LinkTwo();
        //ClearLink();
        //sort();
        //Sort2();
        Sort3();
    
        system("pause");
    }

  • 相关阅读:
    String、StringBuffer与StringBuilder的区别
    案例2:用一条SQL查询出数学语文成绩都大于80分的学生姓名?
    案例1:写一个压缩字符串的方法,例如aaaabbcxxx,则输出a4b2c1x3。
    jsp的九大内置对象及作用
    SQL语句总结2018-11-7
    kafka-spark streaming (一)
    python while嵌套循环
    docker-compose.yml样例(mysql主从+mycat读写分离)
    docker-compose管理daocker
    docker搭建私有registry
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/5217242.html
Copyright © 2011-2022 走看看