本小编是初学数据结构,如果有不对之处或者可改进之处,还望各位读者大哥海涵与告知,先双手源码奉上。
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR -1
#define OK1 2
#define ERROR1 -2
#define OK2 3
#define ERROR2 -3
#define OK3 4
#define ERROR3 -4
#define KONG 5
#define NOKONG -5
#define OVER 6
#define NOFIND -6
typedef struct LNode {
int data; // 数据域
struct LNode* next; // 指针域
} LNode, *LinkList;
// 单链表初始化
int InitList_L(LinkList* L) {
(*L) = (LinkList)malloc(sizeof(LNode)); // 分配头结点空间
if (!(*L)) return ERROR; // 内存分配失败
(*L)->next = NULL; // 头结点指针域置空
return OK;
}
// 判断一个链表是否为空——判断头结点指针域是否为空
int ListEmpty(LinkList L) {
if (L->next)
return KONG;
else
return NOKONG;
}
// 单链表的销毁:链表销毁后不存在——从头指针开始,依次释放所有节点
int DestroyList(LinkList* L) {
LNode* p;
while (*L) {
p = *L;
*L = (*L)->next;
free(p);
}
return OVER;
}
// 求单链表的表长——从首元结点开始,依次计数所有节点
int ListLength(LinkList L) {
LinkList p;
int count = 0;
p = L->next;
while (p) {
count++;
p = p->next;
}
return count;
}
// 取第i个元素的值——从链表的头指针出发,顺着链域next逐个向下搜索,直到搜索到第i个节点为止
// 特殊情况:1. i超过元素个数 2. i < 1
int GetElem_L(LinkList L, int i, int* e) {
LinkList p = L->next;
int j = 1;
while (p && j < i) {
p = p->next;
j++;
}
if (!p || j > i)
return ERROR1; // 位置不合法
*e = p->data;
return OK1;
}
// 查找运算:按值查找位置(地址)——从第一个节点起依次与e比较
LinkList LocateElem_L(LinkList L, int e) {
LinkList p = L->next;
while (p && p->data != e)
p = p->next;
return p;
}
// 查找运算:按值查找位置序号(第几个)——从第一个节点起依次与e比较
int LocateElem_R(LinkList L, int e) {
LinkList p = L->next;
int j = 1;
while (p && p->data != e) {
p = p->next;
j++;
}
if (p)
return j; // 返回位置序号
else
return NOFIND; // 未找到元素
}
// 插入(在第i个节点前插入为e的新节点)
// 1. 找到i-1的存储位置p
// 2. 生成一个数据域为e的新节点s
// 3. 插入新节点(新节点的指针域指向节点i,节点i-1的指针域指向新节点)
int ListInsert_L(LinkList* L, int i, int e) {
LinkList p = *L;
int j = 1;
while (p && j < i) {
p = p->next;
j++;
}
if (!p || j > i)
return ERROR2; // 位置不合法
LinkList s = (LinkList)malloc(sizeof(LNode)); // 生成新节点s
s->data = e;
s->next = p->next; // 插入新节点
p->next = s;
return OK2;
}
// 删除第i个节点
// 1. 找到i-1的存储位置p,保存要删除元素的值
// 2. 令p->next指向i+1
// 3. 释放i的空间
int ListDelete_L(LinkList* L, int i, int* e) {
LinkList p = *L;
int j = 0;
while (p->next && j < i - 1) {
p = p->next;
j++;
} // 寻找第i个节点,并令p指向其前驱
if (!(p->next) || j > i - 1)
return ERROR3; // 删除位置不合理
LinkList q = p->next; // 临时保存被删除节点的地址以备释放
p->next = q->next; // 改变删除节点前驱的指针域
*e = q->data; // 保存删除节点的数据域
free(q); // 释放删除节点的空间
return OK3;
}
// 头插法
void CreateList_H(LinkList* L, int n) {
(*L) = (LinkList)malloc(sizeof(LNode)); // 先建立一个带头结点的单链表
(*L)->next = NULL;
int i, value;
printf("请依次输入%d个整数作为链表元素(从头插入): ", n);
for (i = 0; i < n; ++i) {
LinkList p = (LNode*)malloc(sizeof(LNode)); // 生成新节点p
scanf("%d", &value); // 输入节点的值
p->data = value; // 设置节点的值
p->next = (*L)->next; // 插入到表头
(*L)->next = p;
}
}
//补充9:尾插法
void CreateList_R(LinkList* L, int n) {
(*L) = (LinkList)malloc(sizeof(LNode)); // 先建立一个带头结点的单链表
(*L)->next = NULL;
LinkList r = *L; // r用于指向尾节点
int i;
printf("请依次输入%d个整数作为链表元素(从尾插入): ", n);
for (i = 0; i < n; ++i) {
LinkList p = (LinkList)malloc(sizeof(LNode)); // 生成新节点p
scanf("%d", &(p->data)); // 输入节点的值
p->next = NULL; // 新节点的指针域置空
r->next = p; // 插入到表尾
r = p; // 将尾节点指针指向新节点
}
}
void PrintList(LinkList L) {
L = L->next; // 跳过头结点
while (L != NULL) {
printf("%d ", L->data);
L = L->next;
}
printf("\n");
}
int main() {
LinkList L;
InitList_L(&L); // 初始化链表
int n; // 输入链表长度
printf("请输入链表长度: ");
scanf("%d", &n);
printf("请输入%d个整数作为链表元素: ", n);
CreateList_R(&L, n); // 使用头插法创建链表
//CreateList_H(&L, n); 使用尾插法创建链表
printf("链表元素为: ");
PrintList(L); // 打印链表元素
int length = ListLength(L); // 求链表长度
printf("链表的长度为: %d\n", length);
int value;
printf("请输入要查找的元素值: ");
scanf("%d", &value);
LinkList pos = LocateElem_L(L, value); // 按值查找节点位置
if (pos) {
printf("元素%d在链表中的位置为: %d\n", value, LocateElem_R(L, value));
} else {
printf("元素%d在链表中未找到\n", value);
}
int i;
printf("请输入要获取的节点位置: ");
scanf("%d", &i);
int e;
int status = GetElem_L(L, i, &e); // 获取指定位置节点的值
if (status == OK) {
printf("第%d个节点的值为: %d\n", i, e);
} else {
printf("指定位置不存在节点\n");
}
int insertPos, insertValue;
printf("请输入要插入的位置和值: ");
scanf("%d %d", &insertPos, &insertValue);
status = ListInsert_L(&L, insertPos, insertValue); // 在指定位置插入节点
if (status == OK) {
printf("链表插入成功,插入后的元素为: ");
PrintList(L);
} else {
printf("指定位置不合法\n");
}
int deletePos, deleteValue;
printf("请输入要删除的位置: ");
scanf("%d", &deletePos);
status = ListDelete_L(&L, deletePos, &deleteValue); // 删除指定位置节点
if (status == OK) {
printf("链表删除成功,删除节点的值为: %d,删除后的元素为: ", deleteValue);
PrintList(L);
} else {
printf("指定位置不合法\n");
}
DestroyList(&L); // 销毁链表
if (!L) {
printf("链表已销毁\n");
}
return 0;
}
如果您读完本文章,还请点一个小赞,支持小编继续学习,感谢感谢。