#大二软件工程学生的笔记记载,可能不是很完善,内部有很多问题,但受时间精力等因素限制,可能来不及修改。先只供自用吧,也欢迎大家在下面留言。
----------------------------------正文部分---------------------------------
线性表的存储分为顺序存储和链式存储两种,链式存储里面分为单链表、双链表、循环链表、静态链表。
在链表里面,存在有无头节点之分,当线性表为空表的时候,头结点的指针域为空(可以把它认为是一个锚点,但是内部不存储任何数据信息)。
1.单链表的基本操作
1.1 void InitList(LinkList &L) 构造一个空的带头结点的线性表L。
1.2 bool ListEmpty(LinkList L) 判断带头节点的线性表是否为空
1.3 GetElem_L(LinkList L, int i, ElemType &e 查找第i个结点,将第i个结点的值存入e
1.4 Status ListInsert_L(LinkList &L, int i, ElemType e) / L 为带头结点的单链表的头指针,本算法在链表中第i 个结点之前插入新的元素 e
1.5 ListDelete_L(LinkList &L, int i, ElemType &e) L 为带头结点的单链表的头指针,本算法删除链表中第i 个结点,值储入e
1.6 void ClearList(&L) 将单链表重新置为一个空表
代码部分
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 定义结构
typedef struct LinkNode
{
int number;
struct LinkNode *next;
} linknode;
// 创建带空的头结点
void initList(linknode **L)
{
*L = (linknode *)malloc(sizeof(linknode));
(*L)->next = NULL;
}
// 判断带头结点的线性表是否为空
bool ListEmpty(linknode *L)
{
return L->next == NULL;
}
// 查找第i个节点,将第i个节点的值返回
int GetElem_L(linknode *L, int i)
{
linknode *p_move = L->next; // 从头结点的后继开始
int count = 1;
if (p_move == NULL)
{ // 链表为空
printf("链表为空\n");
return -1; // -1 表示出错
}
while (p_move != NULL && count < i)
{
p_move = p_move->next;
count++;
}
if (p_move == NULL)
{
printf("索引超出范围\n");
return -1; // -1 表示出错
}
return p_move->number;
}
// 在第i个节点之后插入新的元素e
void Listinsert(linknode **L, int e, int i)
{
int count = 1;
linknode *p_move = *L;
while (p_move->next != NULL && count < i)
{
p_move = p_move->next;
count++;
}
linknode *new_node = (linknode *)malloc(sizeof(linknode));
new_node->number = e;
new_node->next = p_move->next;
p_move->next = new_node;
}
// 删除第i个节点
void Listdelete(linknode **L, int i)
{
int count = 1;
linknode *p_move = *L;
while (p_move->next != NULL && count < i)
{
p_move = p_move->next;
count++;
}
if (p_move->next == NULL)
{ // 如果节点不存在
printf("没找到要删除的节点\n");
return;
}
linknode *delete_node = p_move->next;
p_move->next = delete_node->next;
free(delete_node);
}
// 将表置空
void Listclear(linknode **L)
{
linknode *p_move = (*L)->next; // 从第一个元素开始
while (p_move != NULL)
{
linknode *temp = p_move; // 暂存当前节点
p_move = p_move->next; // 移动到下一个节点
free(temp); // 释放当前节点
}
(*L)->next = NULL; // 清空链接
}
// 主函数
int main()
{
linknode *head;
initList(&head);
int choice, value, index;
while (1)
{
printf("请选择操作:\n");
printf("1. 插入元素\n");
printf("2. 删除元素\n");
printf("3. 获取元素\n");
printf("4. 判断链表是否为空\n");
printf("5. 清空链表\n");
printf("6. 退出\n");
printf("输入你的选择: ");
scanf("%d", &choice);
switch (choice)
{
case 1: // 插入元素
printf("输入要插入的元素值: ");
scanf("%d", &value);
printf("输入插入的位置: ");
scanf("%d", &index);
Listinsert(&head, value, index);
break;
case 2: // 删除元素
printf("输入要删除的元素位置: ");
scanf("%d", &index);
Listdelete(&head, index);
break;
case 3: // 获取元素
printf("输入要获取的元素位置: ");
scanf("%d", &index);
value = GetElem_L(head, index);
if (value != -1)
{
printf("第 %d 个节点的值: %d\n", index, value);
}
break;
case 4: // 判断链表是否为空
if (ListEmpty(head))
{
printf("链表为空\n");
}
else
{
printf("链表不为空\n");
}
break;
case 5: // 清空链表
Listclear(&head);
printf("链表已清空\n");
break;
case 6: // 退出
Listclear(&head); // 退出前清空链表
free(head); // 释放头节点的内存
printf("退出程序\n");
return 0;
default:
printf("无效的选择,请重试。\n");
}
}
return 0;
}