特点:逻辑相邻,物理不一定相邻
具体实现之前有几点需要注意
适用于带前驱的操作,比如插入,删除等
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 #include#include //初始化 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); return true; } //按位置删 bool Del_pos(PNode pn, int pos) { assert(pn != NULL); assert(pos>=0&&pos 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"); }
测试文件:



