#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 单链表存储结构
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
// 带头结点的单链表初始化
bool InitList(LinkList &L){
L=(LNode*)malloc(sizeof(LNode)); //创建头结点
L->next = NULL; //头结点的指针,即头结点之后暂时没有元素的结点
return true;
}
//判空操作
int IsEmpty(LinkList L) {
return L->next == NULL; // 头结点的next指向NULL时,表示链表为空
}
//求表长
int GetLength(LinkList L) {
int length = 0;
LNode *p = L->next; // 从头结点的下一个结点开始
while (p != NULL) {
length++;
p = p->next;
}
return length;
}
//按位序查找
LNode* GetElem(LinkList L, int i) {
int j = 1;
LNode *p = L->next;
while (p != NULL && j < i) {
p = p->next;
j++;
}
return p; // 若找到返回指针,若i超出范围则返回NULL
}
//按值查找
LNode* LocateElem(LinkList L, int value) {
LNode *p = L->next;
while (p != NULL) {
if (p->data == value)
return p; // 返回指向该元素的指针
p = p->next;
}
return NULL; // 没有找到
}
//指定结点的后插操作(在p结点之后插入元素e)
int InsertNextNode(LNode *p, int e) {
if (p == NULL) return 0;
LNode *newNode = (LNode*)malloc(sizeof(LNode));
if (newNode == NULL) return 0;
newNode->data = e;
newNode->next = p->next;
p->next = newNode;
return 1; // 插入成功
}
//指定结点的前插操作(在p结点之前插入元素e)——值交换+后插技巧
int InsertPriorNode(LNode *p, int e) {
if (p == NULL) return 0;
LNode *newNode = (LNode*)malloc(sizeof(LNode));
if (newNode == NULL) return 0;
// 把原结点的数据复制到新结点
newNode->data = p->data;
newNode->next = p->next;
// 把新数据放入p,再将p指向新结点
p->data = e;
p->next = newNode;
return 1;
}
//指定结点的前插操作(在p结点之前插入元素e)——遍历找到前驱结点
int InsertBeforeNode(LinkList &L, LNode *p, int e) {
if (L == NULL || p == NULL) return 0;
LNode *pre = L; // 从头结点开始找前驱
while (pre->next != NULL && pre->next != p) {
pre = pre->next;
}
if (pre->next != p) return 0; // p不是链表中的结点
// 找到了前驱,执行后插
return InsertNextNode(pre, e);
}
//按位插入操作
int ListInsert(LinkList &L, int i, int e) {
if (i < 1) return 0; // 位置不合法
LNode *p = L; //指针p当前扫描到的结点
int j = 0; //记录当前节点的位序,头结点是第0个结点
// 找到第i-1个结点
while (p != NULL && j < i - 1) {
p = p->next;
j++;
}
InsertNextNode(p, e);
/*
if (p == NULL) return 0; // 第i-1个结点不存在,插入失败
// 创建新结点
LNode *newNode = (LNode*)malloc(sizeof(LNode));
if (newNode == NULL) return 0; // 内存分配失败
newNode->data = e; // 设置数据
newNode->next = p->next; // 新结点指向原来的下一个结点
p->next = newNode; // 第i-1个结点的next指向新结点
*/
return 1; // 插入成功
}
//按位序删除结点(删除第 i 位元素,返回被删除元素的值)
int ListDelete(LinkList &L, int i, int &e) {
if (i < 1) return 0; // 位置不合法
LNode *p = L;
int j = 0;
// 找到第i-1个结点
while (p != NULL && j < i - 1) {
p = p->next;
j++;
}
if (p == NULL || p->next == NULL) return 0; // 第i-1个结点不存在,删除失败
LNode *q = p->next; // 被删除的结点
e = q->data; // 保存被删除的值
p->next = q->next; // 将第i-1个结点的next指向第i+1个结点
free(q); // 释放被删除结点的内存
return 1; // 删除成功
}
//删除指定结点p(如果p是最后一个结点,只能从表头开始依次寻找p的前驱)
bool DeleteNode(LNode *p){
if(p==NULL)
return false;
LNode *q = p->next;
p->data=p->next->data;
p->next=q->next;
free(q);
return true;
}
void PrintList(LinkList L) {
LNode *p = L->next;
printf("链表元素:");
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//销毁
void DestroyList(LinkList &L) {
LNode *p = (L)->next;
while (p != NULL) {
LNode *temp = p;
p = p->next;
free(temp);
}
free(L); // 释放头结点
L = NULL; // 将链表指针置为NULL
}
//使用尾插法建立单链表(从空表建立)
LinkList List_TailInsert(LinkList &L){
int x;
L=(LNode*)malloc(sizeof(LNode));
LNode *s,*r=L;
scanf("%d",&x);
while(x!=9999){
s=(LNode *)malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s;
scanf("%d",&x);
}
r->next=NULL;
return L;
}
//使用头插法建立单链表(从空表建立)
LinkList List_HeadInsert(LinkList &L){
int x;
L=(LNode*)malloc(sizeof(LNode));
LNode *s;
L->next=NULL;
scanf("%d",&x);
while(x!=9999){
s=(LNode *)malloc(sizeof(LNode));
s->data=x;
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
return L;
}
int main() {
LinkList L;
InitList(L);
// 插入元素
ListInsert(L, 1, 10);
ListInsert(L, 2, 20);
ListInsert(L, 3, 30);
PrintList(L);
// 获取链表长度
printf("链表长度: %d\n", GetLength(L));
// 按值查找
LNode *node = LocateElem(L, 20);
if (node != NULL)
printf("找到值20,数据为: %d\n", node->data);
else
printf("未找到值20\n");
// 按位查找
node = GetElem(L, 2);
if (node != NULL)
printf("第2个元素是: %d\n", node->data);
else
printf("第2个元素不存在\n");
// 删除元素
int deleted;
if (ListDelete(L, 2, deleted))
printf("删除元素: %d\n", deleted);
PrintList(L);
List_TailInsert(L);
PrintList(L);
// 销毁链表
DestroyList(L);
return 0;
}