从一个空表开始,每次读入数据,生成新结点,将读入数据存放到新结点的数据域中,然后将新结点插入到当前表的表头结点之后。
算法实现 # include <stdio.h> # include <stdlib.h> typedef struct Node { int data; struct Node * pNext; }NODE,*PNODE; //遍历 void traverse_list(PNODE pHead)//怎样遍历,是不能像以前一样用数组的,以为数组是连续的,这里不连续 { PNODE p = pHead->pNext; while (NULL != p) { printf("%d ", p->data); p = p->pNext; } printf("\n"); } PNODE create_list(void) { PNODE pHead = (PNODE)malloc(sizeof(NODE)); pHead->pNext = NULL; printf("请输入要生成的链表的长度\n"); int n; int val; scanf("%d",&n); for (int i = n;i > 0;i--) { printf("请输入的第%d个数据",i); PNODE p = (PNODE)malloc(sizeof(NODE));//建立新的结点p if(NULL == p) { printf("内存分配失败,程序终止运行!\n"); exit(-1); } scanf("%d",&val); p->data = val; p->pNext = pHead->pNext;//将p结点插入到表头,这里把头节点的指针赋给了p结点 //此时,可以理解为已经把p节点和头节点连起来了,头指针指向,也就变成了 //p节点的指针指向了(此时的p节点相当于首节点了) pHead->pNext = p; } return pHead; } int main(void) { PNODE pHead = NULL; pHead = create_list(); traverse_list(pHead); return 0; } 运行演示 算法小结采用头插法得到的单链表的逻辑顺序与输入元素顺序相反,所以也称头插法为逆序建表法。为什么是逆序的呢,因为在开始建表的时候,所谓头插法,就是新建一个结点,然后链接在头节点的后面,也就是说,最晚插入的结点,离头节点的距离也就是越近!这个算法的关键是 p->data = val;p->pNext = pHead->pNext; pHead->pNext = p;。用图来表示的话可能更加清晰一些。
线性链表尾插法实现 算法思想头插法建立链表虽然算法简单,但生成的链表中节点的次序和输入顺序相反,如果希望二者的顺序一致,可以采用尾插法,为此需要增加一个尾指针r,使之指向单链表的表的表尾。
算法实现 # include <stdio.h> # include <stdlib.h> typedef struct Node { int data; struct Node * pNext; } NODE,*PNODE; PNODE create_list(void) { PNODE pHead = (PNODE)malloc(sizeof(NODE)); pHead->pNext = NULL; printf("请输入要生成的链表的长度:\n"); int n; int val; PNODE r = pHead;//r 指针动态指向链表的当前表尾,以便于做尾插入,其初始值指向头节点, //这里可以总结出一个很重要的知识点,如果都是指针类型的数据,“=”可以以理解为指向。 scanf("%d",&n); for(int i = 0;i < n;i++) { printf("请输入的第%d个数据",i+1); PNODE p = (PNODE)malloc(sizeof(NODE)); if(NULL == p) { printf("内存分配失败,程序终止运行!"); exit(-1); } scanf("%d",&val); p->data = val; //给新节点p的数据域赋值 r->pNext = p;//因为一开始尾指针r是指向头节点的, 这里又是尾指针指向s // 所以,节点p已经链接在了头节点的后面了 p->pNext = NULL; //把新节点的指针域清空 ,先清空可以保证最后一个的节点的指针域为空 r = p; // r始终指向单链表的表尾,这样就实现了一个接一个的插入 } return pHead; } //遍历 void traverse_list(PNODE pHead)//怎样遍历,是不能像以前一样用数组的,以为数组是连续的,这里不连续 { PNODE p = pHead->pNext; while (NULL != p) { printf("%d ", p->data); p = p->pNext; } printf("\n"); } int main(void) { PNODE pHead = NULL; pHead = create_list(); traverse_list(pHead); return 0; } 运行演示 算法小结通过尾插法的学习,进一步加深了对链表的理解,“=”可以理解为赋值号,也可以理解为“指向”,两者灵活运用,可以更好的理解链表中的相关内容。
还有,这个尾差法其实就是这篇文章中的一开始那个小例子中使用的方法。两者可以比较学习。
在单链表中,由于每个结点 的存储位置都放在其前一个节点的next域中,所以即使知道被访问的节点的序号,也不能想顺序表中那样直接按照序号访问一维数组中的相应元素,实现随机存取,而只能从链表的头指针触发,顺链域next,逐个结点往下搜索,直到搜索到第i个结点为止。
要查找带头节点的单链表中第i个节点,则需要从**单链表的头指针L出发,从头节点(pHead->next)开始顺着链表扫描,用指针p指向当前扫面到的节点,初始值指向头节点,用j做计数器,累计当前扫描过的节点数(初始值为0).当i==j时,指针p所指向的节点就是要找的节点。