C语言链表详解

前言


 学习链表之前,先来看几个术语:
  首节点:存放第一个有效数据的节点;
  尾节点:存放最后一个有效数据的节点;
  头节点:头节点的数据类型与首节点的数据类型相同,并且头节点是首节点前面的那个节点,并不存放有效数据;头节点的存在只是为了方便链表的操作。
  头指针:指向头节点的指针;
  尾指针:指向尾节点的指针。

链表的基本操作



1. 节点的构造

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define LEN sizeof(struct stu)
struct stu
{
    //数据域
    char num[10];
    char name[20];
    float score;
    //指针域
    struct stu * next;
};

2. 建立链表

//建立链表
struct stu * create(){
    //声明头指针,p1和p2两个指针
    struct stu * head;
    struct stu * p1, *p2;

    //建立头结点
    head = (struct stu *) malloc(LEN);
    head->next = NULL;  //头指针指向的头结点的指针域为空

    p1 = head;  //把头指针的指向赋给指针p1,即p1指向头结点
    p2 = (struct stu *)malloc(LEN); //分配第一个节点,并让p2指向他
    printf("输入节点信息:学号、姓名和成绩\n");
    scanf("%s%s%f",p2->num, p2->name, &p2->score);
    getchar();

    //学号为字符串‘0‘作为结束输入的条件
    while(strcmp(p2->num,"0") != 0){
        /*
            执行结束后
                1)p2的next域为NULL.
                2)第一个节点的next域指向第二个节点的数据域
                3)p1指针指向第二个节点的数据域
        */
        p2->next = p1->next;
        p1->next = p2;
        p1 = p2;

        //重新分配第三个节点,并让p2指向他
        p2 = (struct stu *)malloc(LEN);
        printf("输入节点信息:学号、姓名和成绩\n");
        scanf("%s%s%f",p2->num, p2->name, &p2->score);
        getchar();
    }
    //执行结束后释放p2指针,并返回头指针
    free(p2);
    return head;
};

3. 输出链表

//输出链表
void print(struct stu * head){
    struct stu * p; //声明一个p指针
    printf("num name score\n");
    p = head->next; //指针p指向第一个节点

    //依次输出各个节点直到最后一个节点
    while(p!=NULL){
        printf("%-10s %-20s %-4.1f\n",p->num, p->name, p->score);
        p=p->next;
    }
}

4. 插入节点

//插入节点
void insert(struct stu * head, struct stu * p0){
    struct stu *p1, *p2;

    p1 = head->next;    //p1指向第一个节点
    p2 = head;          //p2为待插入节点的前面一个节点

    while((p1!=NULL) && (strcmp(p0->num, p1->num)==1)){ //当p0的学号大于p1的学号并且没有到最后一个时不进行插入
        p2=p1;
        p1=p1->next;
    }

    //下面进行插入操作
    p0->next = p2->next;
    p2->next = p0;
}

5. 删除节点

int delete(struct stu *head, char num[]){
    //声明两个结构体类型的指针,p1和p2
    struct stu *p1, *p2;
    p1 = head->next;    //p1指向第一个节点
    p2 = head;          //p2指向p1的前驱结点

    //查找要删除的节点的位置
    while(p1!=NULL && strcmp(num, p1->num)!=0){
        p2=p1;
        p1=p1->next;
    }

    //要删除的节点不存在
    if(!p1){
        return 0;
    }

    //执行删除操作,并释放p1指针
    p2->next = p1->next;
    free(p1);
    return 1;
}

6. 主函数

//主函数
int main()
{
    struct stu * h, *p0;
    char num[10];
    printf("建立链表\n");
    h = create();
    p0 = (struct stu *)malloc(LEN);

    //测试插入节点的操作
    printf("输入待插入的节点信息:学号、姓名和成绩\n");
    scanf("%s%s%f",p0->num, p0->name, &p0->score);
    getchar();
    if(strcmp(p0->num,"0") != 0){
        insert(h, p0);
    }

    //测试删除节点的操作
    printf("输入待删除节点的学号\n");
    scanf("%s",num);
    if(strcmp(num,"0") != 0){
        delete(h, num);
    }

    printf("输出链表\n");
    print(h);
    return 0;
}

思路总结



1. 创建节点:头节点的指针域初始为空,将新创立的节点依次挂到上面。p1始终指向最后一个节点,p2始终为新建立的节点。
2. 插入节点:先查找该节点要插入的位置,在插入节点。插入的语句为:

p0->next = p2->next;

3. 删除节点:查找要删除的节点的位置,执行插入操作,语句:

p2->next = p1->next;

4. 输出链表:知道头指针,就能知道整个链表

原文地址:http://blog.51cto.com/13416247/2165649

时间: 2024-10-21 10:47:42

C语言链表详解的相关文章

彻底搞定C语言指针详解

1.语言中变量的实质 要理解C指针,我认为一定要理解C中“变量”的存储实质, 所以我就从“变量”这个东西开始讲起吧! 先来理解理解内存空间吧!请看下图: 内存地址→ 6 7 8 9 10 11 12 13 ----------------------------------------------------------------- ... | | | | | | | |.. ------------------------------- ---------------------------

11_Shell语言———管道详解

管道的基本用法为: COMMAND1 | COMMAND2 | COMMAND3 | ... COMMAND1 的输出结果会作为输入参数传递给COMMAND2, COMMAND2加以处理后会传递给COMMAND3, 依此类推.管道的使用便是Linux哲学思想中"组合小程序完成复杂任务"的体现方式. 如果管道的最后一个命令是在当前shell的子shell中执行,那么该执行结果不能保存为一个变量,这样会导致当前shell无法获取执行结果,这是由shell中"本地变量只对当前she

小程序脚本语言WXS详解

WXS脚本语言是 Weixin Script脚本的简称,是JS.JSON.WXML.WXSS之后又一大小程序内部文件类型.截至到目前小程序已经提供了5种文件类型. 解构小程序的几种方式,其中一种方式就是通过文件类型:JS.JSON.WXML.WXSS.WXS.前面四种之前已经介绍过,今天主要是介绍WXS这种文件类型.如果你是PHP.JAVA.C#程序员的话写过服务端代码的话,就很好理解WXS这种脚本语言了.能够更加方便的动态实现页面上的一些基本逻辑判断,而不用全部的依赖后台实现,再通过接口返回.

【数据结构】单链表&amp;&amp;静态链表详解和代码实例

喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 单链表(Singly Linked List ) 1.1 什么是单链表? 单链表是一种链式存储的结构.它动态的为节点分配存储单元.当有节点插入时,系统动态的为结点分配空间.在结点删除时,应该及时释放相应的存储单元,以防止内存泄露.由于是链式存储,所以操作单链表时,必须知道头结点或者头指针的位置.并且,在查找第i个节点时,必须找到第i-1个节点. 1.2 单链表的存储结构代码描述 对于链式存储,通过上一节的讲解相信大家已

c语言scanf详解

函数名: scanf 功 能: 执行格式化输入 用 法: int scanf(char *format[,argument,...]);scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息.可以读入任何固有类型的数据并自动把数值变换成适当的机内格式.其调用格式为:      scanf("<格式化字符串>",<地址表>);scanf()函数返回成功赋值的数据项数,出错时则返回EOF.其控制串由三类字符构成:1.格式化说明符: 2.

Canny边缘检测算法原理及C语言实现详解(原创码字)

Canny算子是John Canny在1986年提出的,那年老大爷才28岁,该文章发表在PAMI顶级期刊上的(1986. A computational approach to edge detection. IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 8, 1986, pp. 679-698).老大爷目前在加州伯克利做machine learning,80-90年代视觉都是图像处理,现在做视觉都是机器

链表详解

转载自http://www.cnblogs.com/lifuqing/archive/2011/08/20/List.html 十分感谢作者 ? #include "stdafx.h" #include "stdio.h" #include <stdlib.h> #include "string.h" typedef int elemType ; /*******************************************

C语言正则表达式详解 regcomp() regexec() regfree()详解

标准的C和C++都不支持正则表达式,但有一些函数库可以辅助C/C++程序员完成这一功能,其中最著名的当数Philip Hazel的Perl-Compatible Regular Expression库,许多Linux发行版本都带有这个函数库. C语言处理正则表达式常用的函数有regcomp().regexec().regfree()和regerror(),一般分为三个步骤,如下所示: C语言中使用正则表达式一般分为三步: 编译正则表达式 regcomp() 匹配正则表达式 regexec() 释

R语言数据结构详解

R有多种存储数据的对象类型.基本的类型可分为: 1.向量 向量中的数据必须拥有相同类型或模式(数值型.字符型.逻辑型):向量类似c语言中的数组:实例:>a<-c(1,2,3,4,5,6)>b<-c(“one”,”two”,”three”)>c<-c(TURE,FALSE,TRUE)标量是指只含一个元素的向量:实例:>e<-3 访问向量中的元素(向量中的元素从1开始,这点与数组不同):>a<-c(1,2,5,7,-5,4) >a[3][1]