特点:逻辑相邻,物理不一定相邻
具体实现之前有几点需要注意
适用于带前驱的操作,比如插入,删除等
for(struct Node *p=pn;p->next!=NULL;p=p->next);//从头节点开始遍历
适用于不带前驱的操作,如打印,查找,获取有效值个数等
for(struct Node *p=pn->next;p!=NULL;p=p->next);//从第一个有效节点开始遍历
插入 1.准备新节点 2.找合适的插入位置 3.插入
删除 1.判空 2.申请一个临时指针,指向待删除节点 3.跨越指向(待删除节点的上一个节点保存待删除节点下一个节点的地址)4.将待删除节点释放
代码实现:头文件(这里的指针域保存着下一个节点的地址)
#pragma once
//单链表有效节点的结构体设计
typedef int ELEM_TYPE;
typedef struct Node {
ELEM_TYPE data;//数据域
struct Node* next;//指针域
}Node,*PNode;
//头节点借助有效节点的结构体设计
//初始化
void Init_List(PNode pn);
//头插
bool Insert_head(PNode pn,ELEM_TYPE value);
//尾插
bool Inseret_tail(PNode pn, ELEM_TYPE value);
//按位置插入
bool Inseret_pos(PNode pn,int pos, ELEM_TYPE value);
//头删
bool Del_head(PNode pn);
//尾删
bool Del_tail(PNode pn);
//按位置删
bool Del_pos(PNode pn,int pos);
//按值删
bool Del_val(PNode pn, ELEM_TYPE value);
//查找
struct Node* Search(PNode pn, ELEM_TYPE value);
//判空
bool IsEmpty(PNode pn);
//获取有效值个数
int Get_length(PNode pn);
//清空
void Clear(PNode pn);
//销毁1
void Destroy1(PNode pn);
//销毁2
void Destroy2(PNode pn);
//打印
void show(PNode pn);
函数的具体实现:
这里需要注意的是:单链表是插入数据是才去申请新节点,且每次只申请一个,所以不存在满的情况,也就不需要扩容。删除之前,需要先将上一个有效节点指向自身的下一个有效节点,然后再去释放自身(如果不这样的话就会导致后面的有效节点丢失,使用的时候无法找到)
#include"list.h"
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
//初始化
void Init_List(PNode pn) {
assert(pn!=NULL);
pn->next = NULL;
}
//头插
bool Insert_head(PNode pn, ELEM_TYPE value) {
assert(pn != NULL);
struct Node* pnewnode=(struct Node*)malloc(sizeof(struct Node));//准备新节点
assert(pnewnode!=NULL);
pnewnode->data = value;
pnewnode->next = NULL;
pnewnode->next = pn->next;
pn->next = pnewnode;
return true;
}
//尾插
bool Inseret_tail(PNode pn, ELEM_TYPE value) {
assert(pn != NULL);
struct Node* pnewnode = (struct Node*)malloc(sizeof(struct Node));//准备新节点
assert(pnewnode != NULL);
pnewnode->data = value;
pnewnode->next = NULL;
struct Node* p=pn;//让指针p也指向头节点
for (p; p->next != NULL; p = p->next);
pnewnode->next = p->next;
p->next = pnewnode;
return true;
}
//按位置插入
bool Inseret_pos(PNode pn, int pos, ELEM_TYPE value) {
assert(pn != NULL);
assert(pos >= 0 && pos <=Get_length(pn));
struct Node* pnewnode = (struct Node*)malloc(sizeof(struct Node));//准备新节点
assert(pnewnode != NULL);
pnewnode->data = value;
struct Node* p = pn;
for (int i = 0; i < pos; i++) {
p = p->next;
}
pnewnode->next = p->next;
p->next = pnewnode;
return true;
}
//头删
bool Del_head(PNode pn) {
assert(pn!=NULL);
if (IsEmpty(pn)) {
return false;
}
struct Node* p = pn->next;
//跨越指向
pn->next=p->next;
free(p);
p = NULL;
return 0;
}
//尾删
bool Del_tail(PNode pn) {
assert(pn != NULL);
int length = Get_length(pn);
if (IsEmpty(pn)) {
return false;
}
Del_pos(pn,length-1);
/*struct Node* p = pn;
for (p; p->next != NULL; p = p->next);
struct Node* q = pn;
for (q; q ->next!= p; q = q->next);
q->next = NULL;
free(p);
p = NULL;*/
return true;
}
//按位置删
bool Del_pos(PNode pn, int pos) {
assert(pn != NULL);
assert(pos>=0&&pos<Get_length(pn));
if (IsEmpty(pn)) {
return false;
}
struct Node* p = pn;
for (int i = 0; i < pos; i++) {
p = p->next;
}
struct Node* q = p->next;
p->next = q->next;
free(q);
return true;
}
//按值删
bool Del_val(PNode pn, ELEM_TYPE value) {
assert(pn != NULL);
if (IsEmpty(pn)) {
return false;
}
struct Node *p=Search(pn,value);
if (p == NULL) {
return false;
}
struct Node* q = pn;
for (q; q->next != p; q = q->next);
q->next = p->next;
free(p);
p = NULL;
return true;
}
//查找
struct Node* Search(PNode pn, ELEM_TYPE value) {
assert(pn!=NULL);
for (struct Node* p = pn->next; p != NULL; p = p->next) {
if (p->data == value) {
return p;
}
}
return NULL;
}
//判空
bool IsEmpty(PNode pn) {
assert(pn!=NULL);
return pn->next == NULL;
}
//获取有效值个数
int Get_length(PNode pn) {
assert(pn!=NULL);
int count = 0;
for (struct Node* p = pn->next; p != NULL; p = p->next) {
count++;
}
return count;
}
//清空
void Clear(PNode pn) {
Destroy1(pn);
}
//销毁1 无限头删
void Destroy1(PNode pn) {
while (!IsEmpty(pn)) {
Del_head(pn);
}
pn->next = NULL;
}
//销毁2
void Destroy2(PNode pn) {
assert(pn!=NULL);
struct Node* p = pn->next;
struct Node* q;
pn->next = NULL;
while (p != NULL) {
q = p->next;
free(p);
p = q;
}
}
//打印
void show(PNode pn) {
for (struct Node* p = pn->next; p != NULL; p = p->next) {
printf("%5d",p->data);
}
printf("\n");
}
测试文件: