C语言之链表
链表
算法
通俗定义:
解题的方法和步骤
狭义定义:
对存储数据的操作
对不同的存储结构,要完成某一个功能所执行的操作是不一样的
比如:
要输出数组中所有的元素的操作和
要输出链表中所有元素的操作肯定是不一样的
这说明:
- 算法是依附于存储结构的
- 不同的存储结构,所执行的算法是不一样的
广义定义:
广义的算法也叫泛型
无论数据是如何存储的,对该数据的操作都是一样的
我们至少可以通过两种结构来存储数据
数组
优点:存储速度快
缺点:
- 需要一个连续的很大的内存
- 插入和删除元素的效率很低
链表
专业术语:
- 头结点:
- 头结点的数据类型和首节点的类型是一摸一样的
- 头结点是首节点前面的那个节点
- 头结点并不存放有效数据
- 设置头节点的目的是为了方便对链表的操作
- 头指针:存放头结点地址的指针变量
- 首节点:存放第一个有效数据的节点
- 尾节点:存放最后一个有效数据的节点
- 确定一个链表需要一个参数:头指针
优点:
- 插入删除元素效率高
- 不需要一个连续的很大的内存
缺点:查找某个位置的元素效率低
1 #define _CRT_SECURE_NO_WARNINGS 1 2 # include <stdio.h> 3 # include <malloc.h> 4 5 //定义了一个链表节点的数据类型 6 struct Node 7 { 8 int data; 9 struct Node* pNext; 10 11 }; 12 13 struct Node* CreateList(void); 14 15 void TraverseList(struct Node*); 16 17 18 int main(void) 19 { 20 21 struct Node * pHead; //pHead用来存放链表头结点的地址 22 23 pHead = CreateList(); //CreateList()功能:用来创建一个非巡航单链表 24 TraverseList(pHead); 25 26 return 0; 27 } 28 29 struct Node * CreateList(void) 30 { 31 int len; //用来存放有效节点的个数 32 int i; 33 int val; //用来临时存放用户输入的结点的值 34 35 //分配了一个不存放有效数据的头结点 36 struct Node * pHead = (struct Node *)malloc(sizeof(struct Node)); 37 38 if (NULL == pHead) 39 { 40 printf("分配失败,程序中止!\n"); 41 return NULL; 42 } 43 44 struct Node * pTail = pHead; 45 pTail->pNext = NULL; 46 47 printf("请输入您需要生成的链表节点的个数:len="); 48 scanf("%d", &len); 49 50 for (int i = 0;i < len;i++) 51 { 52 printf("请输入第%d个节点的值:", i + 1); 53 scanf("%d", &val); 54 55 struct Node* pNew = (struct Node*)malloc(sizeof(struct Node)); 56 57 if (NULL == pNew) 58 { 59 printf("分配失败,程序中止!\n"); 60 return NULL; 61 } 62 63 pNew->data = val; 64 pTail->pNext = pNew; 65 pNew->pNext = NULL; 66 pTail = pNew; 67 68 } 69 return pHead; 70 } 71 72 73 void TraverseList(struct Node * pHead) 74 { 75 struct Node * p = pHead->pNext; 76 77 while (NULL != p) 78 { 79 printf("%d\t", p->data); 80 p = p->pNext; 81 } 82 printf("\n"); 83 84 return; 85 }