链表
链表的专业术语:
- 首节点:存放第一个有效数据的结点;
- 尾结点:存放最后一个有效数据的结点;尾指针指向;
- 头结点:头结点的数据类型和首结点的类型一模一样;
头结点是首节点前面的那个结点;
头结点并不存放有效数据;
设置头结点的目的是为了方便存储数据;
- 头指针:存放头结点地址的指针变量,指向头结点;
单链表的插入实现逻辑:
链表插入的核心语句:
Step 1:s->next=p->next;
Step 2:p->next=s ;
单链表的删除实现逻辑:
删除动作的核心语句(要借助辅助指针变量q):
q = p->next; //首先保存b的指针,靠它才能找到c;
p->next=q->next; //将a、c两结点相连,淘汰b结点;
free(q) ; //彻底释放b结点空间
实现
- 以下代码实现了链表的插入,删除,反转,遍历
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAXSIZE (10)
typedef int ElementType;
typedef struct Node {
ElementType data;
struct Node *Next;
} *List;
List CreateList(void) //建表,初始化为空
{
List L = (List)malloc(sizeof(struct Node));
if (L == NULL) {
printf("Out of space!");
return NULL;
}
L->data = 0;
L->Next = NULL;
return L;
}
List InitList(List L) //初始化链表
{
List rear = L;
srand((unsigned)time(NULL));
for (int i = 0; i < MAXSIZE; i++) {
List p = (List)malloc(sizeof(struct Node));
p->data = rand() % 100; //生成10个随机数,范围0~100
rear->Next = p;
rear = p;
}
rear->Next = NULL;
}
void PrintList(List L) //遍历
{
List head = L->Next;
while (head) {
printf("%d ", head->data);
head = head->Next;
}
printf("\n");
}
void ReverseList(List L) //反转
{
List head = L->Next;
List tmp = L->Next->Next;
head->Next = NULL;
List p = NULL;
while (tmp) {
p = tmp;
tmp = tmp->Next;
p->Next = head;
head = p;
}
L->Next = head;
}
void DeleteEven(List L) //删除
{
List p = L;
List q;
while (p->Next) {
q = p->Next;
if (q->data % 2 == 0) {
p->Next = q->Next;
free(q); //删除里面所有的偶数
} else {
p = p->Next;
}
}
}
void Insert(List L) //插入
{
int input;
List p = L;
List q = L->Next;
List tmp = (List)malloc(sizeof(struct Node));
printf("please input specify number to insert: ");
scanf("%d", &input);
tmp->data = input;
while (q && (q->data < input)) {
p = p->Next;
q = p->Next; //将输入的数据按大小插入链表
}
tmp->Next = q;
p->Next = tmp;
}
int main(void)
{
List L = CreateList();
InitList(L);
PrintList(L);
ReverseList(L);
PrintList(L);
DeleteEven(L);
PrintList(L);
Insert(L);
PrintList(L);
return 0;
}
- 运行结果如图