头插法

核心代码:
head->next = NULL;
s->next = head->next;
head->next = s;

单个结点

原始状态

第一个元素插入的过程(注意:1和2的顺序不能颠倒,不然会导致链表缺失


第一个元素插入后

第二个元素插入的过程(其余元素插入的过程也类似)


第二个元素插入后

尾插法

核心代码:
tail = head;
s->next = NULL;
tail->next = s;
tail = s;

原始状态

第一个元素插入的过程(注意:2和3的顺序不能颠倒,不然会导致链表的生成出错


第一个元素插入后

第二个元素插入的过程(其余元素插入的过程也类似)


第二个元素插入后

头插法和尾插法的对比

头插法建立链表的算法简短易懂,但是生成链表的结点顺序与原来输入的顺序相反,而用尾插法建立链表可使输入和生成的结点顺序相同

为什么会这样呢?
根据上面的头插法和尾插法的算法,我们很容易知道,当用头插法依次插入值分别为1,2,3,4,5的结点(也叫做元素)后,单链表会如下图所示:

但是用尾插法同样插入值分别为1,2,3,4,5的结点后,单链表却会如下图所示:

而在这两个链表中,输出链表中各个元素的值只能从已知的头结点head开始遍历,所以分别用头插法和尾插法创建链表后,依次输出的元素的值刚好是相反的


验证小例子:

#include #include typedef struct node{struct node* next;int data; }LinkList;  //定义LinkList为struct node类型,即struct node可直接用LinkList来表示,方便定义 //头插法创建单链表 int main (void){int i, len = 5;//len表示链表的长度LinkList* head, * s;//head为LinkList*类型的指针变量,表示头指针head = (LinkList*)malloc (sizeof (LinkList));//malloc (sizeof (LinkList))意思是让系统分配内存大小为sizeof (LinkList)的空间head->next = NULL;//令头指针的所指向结点的指针域为空for (i = 0; i < len; i++){s = (LinkList*)malloc (sizeof (LinkList));printf ("请输入该元素的值:");scanf ("%d", &s->data);s->next = head->next;head->next = s;}//以下代码是为了将单链表中各个元素的值依次打印出来LinkList* q;q = (LinkList*)malloc (sizeof (LinkList));q = head->next;while (q != NULL){printf ("%d", q->data);q = q->next;}return 0;}

结果:
请输入该元素的值:1
请输入该元素的值:2
请输入该元素的值:3
请输入该元素的值:4
请输入该元素的值:5
54321

#include #include typedef struct node{struct node* next;int data; }LinkList;  //尾插法创建单链表int main (void){int i, len = 5;LinkList* head,* s,* tail;//tail表示尾指针head = (LinkList*)malloc (sizeof (LinkList));tail = head;for (i = 0; i < len; i++){s = (LinkList*)malloc (sizeof (LinkList));printf ("请输入该元素的值:");scanf ("%d", &s->data); s->next = NULL;tail->next = s;tail = s;    } //以下代码是将单链表中各个元素的值依次打印出来       LinkList* q;    q = head->next;    while (q != NULL)    {    printf ("%d", q->data);    q = q->next;}    return 0; } 

结果:
请输入该元素的值:1
请输入该元素的值:2
请输入该元素的值:3
请输入该元素的值:4
请输入该元素的值:5
12345