数据结构 第二章 线性表 单链表

#大二软件工程学生的笔记记载,可能不是很完善,内部有很多问题,但受时间精力等因素限制,可能来不及修改。先只供自用吧,也欢迎大家在下面留言。

----------------------------------正文部分---------------------------------

线性表的存储分为顺序存储和链式存储两种,链式存储里面分为单链表、双链表、循环链表、静态链表。

在链表里面,存在有无头节点之分,当线性表为空表的时候,头结点的指针域为空(可以把它认为是一个锚点,但是内部不存储任何数据信息)。

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值