数组与链表的对比
数组
数组的优点
数组的缺点
- 需要一个连续的很多的内存;
-
链表
链表的优点
插入和删除元素效率高;
-
链表的缺点
链表的定义
首节点
尾结点
存放最后一个有效数据的节点。其中,下一个数据的指针为NULL(类似于字符串的结束符”\0”)。
头结点
头结点的数据类型和首节点的数据类型相同;
- 头结点是首节点的上一个节点;
- 头结点并不存放有效数据;
- 设置头结点的目的是为了方便对链表的操作;
- 头结点不是必须的。
头指针
存放头结点地址的指针变量。确定一个链表所需的参数
确定一个链表只需要一个参数,即头指针的地址(尾结点的数据指针为NULL,可判断为结束符)。 ```c 链表示例:
include
struct Node { int data; struct Node pNext; }; int main(void) { struct Node pHead = NULL; //声明一个链表头指针 pHead = create_list(); //头指针指向链表 traverse_list(pHead); //传输链表
return 0;
}
<a name="RDBSw"></a>
## 创建一个链表
1. **创建一个头指针;**
1. **创建一个头结点(可选);**
1. **创建多个存储数据的节点(创建过程中要做好逻辑关系)**。
```c
#include <stdio.h>
#define LIST_LEN 5
struct Node
{
int data;
struct Node *pNext;
};
struct Node *create_list(void)
{
//struct Node *p = NULL; //创建一个头指针
//创建一个不存放有效数据的头结点
struct Node * pHead = (struct Node *)malloc(sizeof(struct Node));
if(NULL == pHead) //判断头结点是否创建成功
{
printf("链表头结点分配失败\n");
exit(-1);
}
//头指针指向头结点
//p = pHead;
struct Node *pTemp = pHead; //创建一个临时指针指向头结点
for(int i = 0;i < LIST_LEN;i++)
{
//创建一个新的节点
struct Node * pNew = (struct Node *)malloc(sizeof(struct Node));
if(NULL == pNew) //判断新节点是否创建成功
{
printf("链表新节点分配失败\n");
exit(-1);
}
//新节点初始化
pNew->data = i; //填充链表数据
pNew->pNext = NULL; //指针初始化为NULL
//通过临时指针建立链表逻辑关系
pTemp->pNext = pNew; //上一个链表元素的指针指向pNew
pTemp = pTemp->pNext; //替换临时指针为当前pNew----pTemp->pNext其实就是上一行代码的pNew
}
return pHead;
}
遍历输出一个链表
#include <stdio.h>
struct Node
{
int data;
struct Node *pNext;
};
void traverse_list(struct Node *pHead)
{
struct Node *p = pHead->pNext; //定义结构体指针,指向下一个数据的指针
while(NULL != p) //判断该指针是否为空--空则为链表末位
{
printf("%d\n",p->data); //循环输出链表数据
p = p->pNext; //p指向下一个元素的指针
}
}