引入

前面我们学习了头插法创建单链表,既然有头插法就有尾插法,跟头插法思路相同,尾插法是在表尾加入新结点,我们一起来看一下。

尾插法创建单链表

头插法学习完之后,我们发现输入和输出的内容是相反的?为什么呢?因为头插法是在链表的头部插入数据,先插入的数据在尾部,后插入的数据再头部,所以最终保存的链表顺序跟输入顺序是相反的。尾插法就不存在这个问题,输入顺序跟输出顺序相同。

代码实现

#include <stdio.h>
#include <stdlib.h>
#define LEN sizeof(struct Student)
struct Student{
    int num;
    char name[20];
    float score;
    struct Student *next;
};

struct Student *create(void){
    struct Student *a,*b,*head;
    a=(struct Student *)malloc(LEN);  //创建结点
    head=(struct Student *)malloc(LEN); //创建头部
    b=head;  //b 指向尾巴,现在指向头部
    printf("请输入学生信息:\n");
    scanf("%d %s %f",&a->num,a->name,&a->score);
    while(a->num!=0){
        b->next=a;  //b在队尾,b 的 next 指向尾巴 a
        //也可以理解为:让 b 始终指向最后一个结点
        b=a;  //将 b 指向新节点,永远都指向新生成的节点
        //也可以理解为:让 r 始终在最后
        a=(struct Student *)malloc(LEN);
        scanf("%d %s %f",&a->num,a->name,&a->score);
    }
    b->next=NULL;
    return head;
}

void print(struct Student * p){
    p=p->next;
    while(p!=NULL){
        printf("%d号%s的成绩是:%3.1f\n",p->num,p->name,p->score);
        p=p->next;
    }
}

int main(){
    struct Student* stu_p;
    stu_p=create();
    print(stu_p);
    return 0;
}

输出结果
请输入学生信息:
10001 liulin 99
10002 lin 99.9
10003 bliner 100
0 0 0
10001号liulin的成绩是:99.0
10002号lin的成绩是:99.9
10003号bliner的成绩是:100.0

只要清楚这个逻辑就行:

  • 注意新加的这个 b
  • b 是 a 的替身,用于指向新的 a
  • b 永远指向最新的结点,b 永远等于最新的结点,所以 b 永远在最后
  • 这样就保证,新加的结点在末尾了

伪代码实现

#include <stdio.h>
#include <time.h>
#define ERROR 0
#define OK 1
typedef int Elemtype
struct Node{
Elemtype data;
struct Node * next;
};
//构建单链表
typedef struct Node* LinkList;

void CreateListHead(LinkList *L , int n){
LinkList *p *r;
int i;
srand((time(0))); //设置随机数种子

L=(LinkList *)malloc(sizeof(Node));
r=L;  //永远都指向尾巴的 r
(*L)->next=NULL;

for( i=0; i<n; i++){
p = (Node *)malloc(sizeof(Node));  //产生新结点
p->data =rand()%100+1;  //随机数取余100,就是100以内的随机数
r->next=p;  //让 r 永远指向新节点
r=p;  //让 r 永远在最后
}
r->next=NULL;
}

尾巴

这是我的个人学习笔记,主要是应付考研复习使用,充斥着一些吐槽和个人观点,并不严谨,欢迎大家参考、指正。