#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
//本单链表是带头节点的
//为方便理解,本程序未进行公共代码提取成方法
//定义一个单链表
typedef struct Lnode {
int data; //这个节点存储的数据
struct Lnode *next; //自引用指针,这个节点的指针域,指向下一个节点
} Lnode;
//初始化单链表
Lnode *InitList() {
Lnode *L = (Lnode *) malloc(sizeof(Lnode)); //为头指针分配一个内存空间
//判断内存空间是否分配成功
if (L == NULL) {
return NULL;
}
L->next = NULL;
return L;
}
//按位序插入元素,第i个位置插入第e个元素
bool ListInsert(Lnode *L, int i, int e) {
//插入索引异常
if (i < 1) {
return false;
}
//p指向头指针
Lnode *p = L;
//用来计算当前p指向的是第几个节点
int j = 0;
//找到插入节点的前一个位置
while (p != NULL && j < i - 1) {
p = p->next;
j++;
}
//i值超出单链表长度
if (p == NULL) {
return false;
}
//定义一个节点
Lnode *s = (Lnode *) malloc(sizeof(Lnode));
if (s == NULL) {
return false;
}
//插入节点
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
//指定节点的后插操作 在p节点后插入一个数据
bool InsertNextNode(Lnode *p, int e) {
if (p == NULL) {
return false;
}
//定义一个节点
Lnode *l = (Lnode *) malloc(sizeof(Lnode));
//判断内存是否分配成功
if (l == NULL) {
return false;
}
//插入节点
l->data = e;
l->next = p->next;
p->next = l;
return true;
}
//指定节点的前插操作
bool InsertBeforeNode(Lnode *p, int e) {
//判断节点是否存在
if (p == NULL) {
return false;
}
Lnode *s = (Lnode *) malloc(sizeof(Lnode));
//判断内存是否分配成功
if (s == NULL) {
return false;
}
//先在p节点后插入s节点,再把p节点的数据复制到s节点,
//要插入的数据赋值于p节点,以实现前插操作
s->next = p->next;
p->next = s;
s->data = p->data;
p->data = e;
return true;
}
//按位序删除元素,第i个位置删除元素,用e存储删除的元素
bool ListDelete(Lnode *L, int i, int *e) {
//删除索引异常
if (i < 1) {
return false;
}
//p指向头指针
Lnode *p = L;
//用来计算当前p指向的是第几个节点
int j = 0;
//找到删除节点的前一个位置
while (p != NULL && j < i - 1) {
p = p->next;
j++;
}
//i值超出单链表长度
if (p == NULL) {
return false;
}
//i节点已没有节点
if (p->next == NULL) {
return false;
}
//删除节点
Lnode *s = p->next; //s为要删除的节点
*e = s->data; //e存储删除节点的值
//断开s节点
p->next = s->next;
s->next = NULL;
//释放资源
free(s);
return true;
}
//指定节点的删除(不包含头结点和最后一个节点)
//头节点不能被删除,此处并未进行逻辑判断
//若p为最后一个节点,需找到前一个节点把其指针域赋值为NNll即可
bool DeleteNode(Lnode *p) {
//节点不存在
if (p == NULL) {
return false;
}
Lnode *s = p->next; //s为删除节点的后一个节点
p->data = s->data; //p节点数据域覆盖
p->next = s->next; //p节点指针域覆盖
free(s); //释放资源
return true;
}
//按位查找
Lnode *GetElem(Lnode *l, int i) {
//判断i是否合理
if (i < 0) {
return NULL;
}
//定义指针p指向头指针
Lnode *p;
p = l;
//判断p指向的是第几个节点
int j = 0;
//找到第i个节点
while (p != NULL && j < i) {
p = p->next;
j++;
}
return p;
}
//按值查找
Lnode *LocateElem(Lnode *l, int e) {
//定义指针p指向头指针
Lnode *p = l;
//进行遍历查找
while (p != NULL && p->data != e) {
p = p->next;
}
//单链表没有该值
if (p == NULL) {
return NULL;
}
return p;
}
//尾插法建立单链表
Lnode *List_TailInsert() {
//初始化单链表
Lnode *p = InitList();
//定义表尾指针
Lnode *s = p;
//插入的节点
Lnode *prev;
for (int i = 1; i <= 10; i++) {
//为插入节点分配内存空间
prev = (Lnode *) malloc(sizeof(Lnode));
prev->data = i; //插入节点赋值
s->next = prev; //连接链表
s = prev; //表尾节点更换
}
//尾节点指针域为空
s->next = NULL;
return p;
}
//头插法建立单链表
Lnode *List_HeadInsert() {
//初始化单链表
Lnode *p = InitList();
//插入的节点
Lnode *prev;
for (int i = 1; i <= 10; i++) {
//为插入节点分配内存空间
prev = (Lnode *) malloc(sizeof(Lnode));
prev->data = i; //插入节点赋值
prev->next = p->next; //插入节点指针域赋值
p->next = prev; //头结点和插入指针建立关系
}
return p;
}
//测试
void main(void) {
//尾插法建立单链表
printf("尾插法\n");
Lnode *p = List_TailInsert();
//测试数据用的节点
Lnode *p1 = p;
Lnode *p2 = p;
Lnode *p3 = p;
Lnode *p4 = p;
for (int i = 0; i < 10; i++) {
p = p->next;
printf("%d\t", p->data);
}
printf("\n");
//查找
Lnode *s1 = GetElem(p1, 2);
printf("%d\n", s1->data);
Lnode *s2 = LocateElem(p2, 8);
printf("%d\n", s2->data);
//增加
ListInsert(p3, 3, 2);
for (int i = 0; i < 11; i++) {
p3 = p3->next;
printf("%d\t", p3->data);
}
printf("\n");
//重置为第二个节点;
p3 = p4->next->next;
InsertNextNode(p3, 10);
//重置为指向头节点的指针
p3 = p4;
for (int i = 0; i < 12; i++) {
p3 = p3->next;
printf("%d\t", p3->data);
}
//删除操作同增加
printf("\n头插法\n");
Lnode *h = List_HeadInsert();
for (int i = 0; i < 10; i++) {
h = h->next;
printf("%d\t", h->data);
}
}