C++数据结构之单链表的实现

目录
  • 一、单链表的定义
  • 二、单链表的基本操作的实现
    • 1.初始化
    • 2.取值
    • 3.查找
    • 4.插入
    • 5.删除
  • 三、完整代码
  • 四、测试一下代码

一、单链表的定义

线性表的链式存储又称为单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表结点,除存放元素自身的信息外,还需要存放一个指向其后继的指针。

单链表中结点类型的描述如下:

typedef struct  LNode{  // 定义单链表节点类型
  ElemType data;    // 数据域
  struct LNode* next; // 指针域
};LNode, *LinkList;

二、单链表的基本操作的实现

1.初始化

单链表的初始化操作就是构造一个空表。

具体代码:

// 初始化单链表
void InitList(LinkList &L) // 构造一个空的单链表L
{
  L=new LNode;  // 生成新节点作为头节点,用头指针L指向头节点
  L->next=NULL; // 头节点的指针域置空
}

2.取值

和顺序表不同,在链表中并没有存储在物理相邻的单元中。所以我们只能从链表的首节点出发,顺着链域next逐个节点向下访问。

具体代码:

// 单链表的取值
bool GetElem(LinkList L, int i, ElemType &e)
{
  LinkList p=L->next;int j=1; // 初始化,p指向首元节点,计数器j初值为1
  while(p&&j<i) // 顺着链域向后查找,直到p为空或p指向第i个元素
  {
    p=p->next;  // p指向下一个节点
    ++j;  // 计数器j相应加1
  }
  if(!p||j>i)return false;   // i值不合法
  e=p->data;  // 取第i个节点的数据域
  return true;
}

3.查找

从链表的首元节点出发,依次将节点值和给定值e进行比较,返回查找结果。

具体代码:

//单链表的查找
bool LocateElem(LinkList L, LNode*& p, ElemType e)
{
  //在单链表中查找第一个数据为e的结点
  p = L->next;//p指向首元结点
  while (p && p->data != e)
  {
    p = p->next;
  }
  if (p)
  {
    return true;
  }
  return false;
}

4.插入

// 单链表的插入
bool ListInsert(LinkList &L, int i, ElemType e)
{

  LinkList p = L;
  LNode* s;
  int j = 0;
  while (p && j < i - 1)//p指向第i-1个结点
  {
    p = p->next;
    j++;
  }
  if (!p || i < 1)//i大于表长+1或小于1,插入位置不合法
  {
    return false;
  }
  s = new LNode;
  s->data = e;
  s->next = p->next;
  p->next = s;
  return true;
}

5.删除

//单链表的删除
bool ListDelete(LinkList& L, int i, ElemType& e)
{
  //将单链表的第i个结点删除
  LinkList p = L;
  LNode* q;
  int j = 0;
  while (p->next && j < i - 1)//p指向第i-1个结点
  {
    p = p->next;
    j++;
  }
  if (!(p->next) || i < 1)//i大于表长或小于1,删除位置不合法
  {
    return false;
  }
  q = p->next;//临时保存被删结点的地址以备释放
  p->next = q->next;
  e = q->data;//保存被删结点的数据
  delete q;//释放被删结点的空间
  return true;
}

三、完整代码

#include<iostream>
using namespace std;
#define ElemType int

typedef struct  LNode{  // 定义单链表节点类型
  ElemType data;    // 数据域
  struct LNode* next; // 指针域
}LNode,*LinkList;

// 初始化单链表
void InitList(LinkList &L) // 构造一个空的单链表L
{
  L=new LNode;  // 生成新节点作为头节点,用头指针L指向头节点
  L->next=NULL; // 头节点的指针域置空
}

//单链表的创建
void CreateList_H(LinkList& L)//前插法创建单链表
{
  //创建一个长度为n的单链表L,逆序位插入
  int n;
  LNode *p;
  cout << "请输入创建的单链表长度:" << endl;
  cin >> n;
  for (int i = 0; i < n; i++) {
    p = new LNode;
    cout << "请输入插入的第" << i + 1 << "个数据值" << endl;
    cin >> p->data;
    p->next = L->next;
    L->next = p;
  }
}

// 单链表的取值
bool GetElem(LinkList L, int i, ElemType &e)
{
  LinkList p=L->next;int j=1; // 初始化,p指向首元节点,计数器j初值为1
  while(p&&j<i) // 顺着链域向后查找,直到p为空或p指向第i个元素
  {
    p=p->next;  // p指向下一个节点
    ++j;  // 计数器j相应加1
  }
  if(!p||j>i)return false;   // i值不合法
  e=p->data;  // 取第i个节点的数据域
  return true;
}

//单链表的查找
bool LocateElem(LinkList L, LNode*& p, ElemType e)
{
  //在单链表中查找第一个数据为e的结点
  p = L->next;//p指向首元结点
  while (p && p->data != e)
  {
    p = p->next;
  }
  if (p)
  {
    return true;
  }
  return false;
}

// 单链表的插入
bool ListInsert(LinkList &L, int i, ElemType e)
{

  LinkList p = L;
  LNode* s;
  int j = 0;
  while (p && j < i - 1)//p指向第i-1个结点
  {
    p = p->next;
    j++;
  }
  if (!p || i < 1)//i大于表长+1或小于1,插入位置不合法
  {
    return false;
  }
  s = new LNode;
  s->data = e;
  s->next = p->next;
  p->next = s;
  return true;
}

//单链表的删除
bool ListDelete(LinkList& L, int i, ElemType& e)
{
  //将单链表的第i个结点删除
  LinkList p = L;
  LNode* q;
  int j = 0;
  while (p->next && j < i - 1)//p指向第i-1个结点
  {
    p = p->next;
    j++;
  }
  if (!(p->next) || i < 1)//i大于表长或小于1,删除位置不合法
  {
    return false;
  }
  q = p->next;//临时保存被删结点的地址以备释放
  p->next = q->next;
  e = q->data;//保存被删结点的数据
  delete q;//释放被删结点的空间
  return true;
}

四、测试一下代码

#include<iostream>
using namespace std;
#define ElemType int

//************************单链表的存储结构********************
typedef struct LNode
{
  ElemType data;//结点的数据域
  struct LNode* next;//结点的指针域
}LNode, * LinkList;//LinkList为指向结构体LNode的指针类型

//***********************单链表的基本操作函数******************

//单链表的初始化
void InitList(LinkList& L)
{
  //构造一个空的单链表
  L = new LNode;
  L->next = NULL;
}
//单链表的创建
void CreateList_H(LinkList& L)//前插法创建单链表
{
  //创建一个长度为n的单链表L,逆序位插入
  int n;
  LNode* p;
  cout << "请输入创建的单链表长度:" << endl;
  cin >> n;
  for (int i = 0; i < n; i++)
  {
    p = new LNode;
    cout << "请输入插入的第" << i + 1 << "个数据值" << endl;
    cin >> p->data;
    p->next = L->next;
    L->next = p;
  }
}

void CreateList_R(LinkList& L)//后插法创建单链表
{
  //创建一个长度为n的单链表L,正序位插入
  int n;
  LNode* p, * r;
  r = L;//尾指针r指向头结点
  cout << "请输入创建的单链表长度:" << endl;
  cin >> n;
  for (int i = 0; i < n; i++)
  {
    p = new LNode;
    cout << "请输入插入的第" << i + 1 << "个数据值" << endl;
    cin >> p->data;
    p->next = NULL;
    r->next = p;
    r = p;
  }
}

//单链表的插入
bool ListInsert(LinkList& L, int i, ElemType e)
{
  //在带头结点的单链表L的第i个结点前插入新结点
  LinkList p = L;
  LNode* s;
  int j = 0;
  while (p && j < i - 1)//p指向第i-1个结点
  {
    p = p->next;
    j++;
  }
  if (!p || i < 1)//i大于表长+1或小于1,插入位置不合法
  {
    return false;
  }
  s = new LNode;
  s->data = e;
  s->next = p->next;
  p->next = s;
  return true;
}

//单链表的删除
bool ListDelete(LinkList& L, int i, ElemType& e)
{
  //将单链表的第i个结点删除
  LinkList p = L;
  LNode* q;
  int j = 0;
  while (p->next && j < i - 1)//p指向第i-1个结点
  {
    p = p->next;
    j++;
  }
  if (!(p->next) || i < 1)//i大于表长或小于1,删除位置不合法
  {
    return false;
  }
  q = p->next;//临时保存被删结点的地址以备释放
  p->next = q->next;
  e = q->data;//保存被删结点的数据
  delete q;//释放被删结点的空间
  return true;
}

//单链表的取值
bool GetElem(LinkList L, int i, ElemType& e)
{
  //获取单链表中第i个结点的数据
  LinkList p = L;
  int j = 0;
  while (p->next && j < i - 1)//p指向第i-1个结点
  {
    p = p->next;
    j++;
  }
  if (!(p->next) || i < 1)//i大于表长或小于1,第i个结点不存在
  {
    return false;
  }
  e = p->next->data;//获取第i个结点的数据
  return true;
}

//单链表的查找
bool LocateElem(LinkList L, LNode*& p, ElemType e)
{
  //在单链表中查找第一个数据为e的结点
  p = L->next;//p指向首元结点
  while (p && p->data != e)
  {
    p = p->next;
  }
  if (p)
  {
    return true;
  }
  return false;
}

//*********************************单链表的基本功能函数******************************

//1、插入
void ListInsert(LinkList& L)
{

  ElemType e;
  int i;
  bool flag;
  cout << "请输入要插入的数据:" << endl;
  cin >> e;
  cout << "请输入要插入的位置:" << endl;
  cin >> i;
  flag = ListInsert(L, i, e);
  if (flag)
    cout << "插入成功!" << endl;
  else
    cout << "位置不对,插入失败!" << endl;
}

//2、删除
void ListDelete(LinkList& L)
{
  ElemType e;
  int i;
  bool flag;
  cout << "请输入要删除数据的位置:" << endl;
  cin >> i;
  flag = ListDelete(L, i, e);
  if (flag)
    cout << "删除成功,删除的数据为:" << e << endl;
  else
    cout << "位置不对,删除失败!" << endl;
}

//3、取值
void GetElem(LinkList L)
{
  ElemType e;
  int i;
  bool flag;
  cout << "请输入要获取数据的位置:" << endl;
  cin >> i;
  flag = GetElem(L, i, e);
  if (flag)
    cout << "获取的数据为:" << e << endl;
  else
    cout << "位置不对,获取数据失败!" << endl;
}

//4、查找
void LocateElem(LinkList L)
{
  ElemType e;
  LNode* p = NULL;
  bool flag;
  cout << "请输入要查找的数据:" << endl;
  cin >> e;
  flag = LocateElem(L, p, e);
  if (flag)
    cout << "查找成功,该数据的地址为:" << p << endl;
  else
    cout << "查找失败!" << endl;
}

//5、判空
void ListEmpty(LinkList L)
{
  if (L->next)
    cout << "链表不为空!" << endl;
  else
    cout << "链表为空!" << endl;
}

//6、求长
void ListLength(LinkList L)
{
  LinkList p = L->next;//p指向第一个结点
  int i = 0;
  while (p)//遍历单链表,统计结点数
  {
    i++;
    p = p->next;
  }
  cout << "链表的长度为:" << i << endl;
}

//7、清空
void ClearList(LinkList& L)
{
  LNode* p, * q;
  p = L->next;
  while (p)//从首元结点开始,依次删除
  {
    q = p->next;
    delete p;
    p = q;
  }
  L->next = NULL;//头结点指针域置空
}

//8、销毁
void DestroyList(LinkList& L)
{
  LNode* p;
  while (L)//从头结点开始依次删除
  {
    p = L;
    L = L->next;
    delete p;
  }
}

//9、打印
void PrintList(LinkList L)
{
  LinkList p = L->next;//p指向第一个结点
  int i = 0;
  while (p)//遍历单链表
  {
    i++;
    cout << "链表第" << i << "个数据为:" << p->data << endl;
    p = p->next;
  }
}

//菜单
void menu()
{
  cout << "***************************************************************************" << endl;
  cout << "***********************************1、插入*********************************" << endl;
  cout << "***********************************2、删除*********************************" << endl;
  cout << "***********************************3、取值*********************************" << endl;
  cout << "***********************************4、查找*********************************" << endl;
  cout << "***********************************5、判空*********************************" << endl;
  cout << "***********************************6、求长*********************************" << endl;
  cout << "***********************************7、清空*********************************" << endl;
  cout << "***********************************8、销毁*********************************" << endl;
  cout << "***********************************9、打印*********************************" << endl;
  cout << "***********************************0、退出*********************************" << endl;
  cout << "***************************************************************************" << endl;
}

int main()
{
  LinkList L;
  InitList(L);
  int select;
  cout << "请先创建单链表:1、前插法!  2、后插法!" << endl;
  cin >> select;
  switch (select)
  {
  case 1://插入
    CreateList_H(L);
    system("pause");//按任意键继续
    break;
  case 2://删除
    CreateList_R(L);
    system("pause");
    break;
  default:
    cout << "输入有误,创建失败!" << endl;
    system("pause");
    break;
  }
  while (1)
  {
    system("CLS");//清屏操作
    menu();
    cout << "请输入菜单序号:" << endl;
    cin >> select;
    switch (select)
    {
    case 1://插入
      ListInsert(L);
      system("pause");//按任意键继续
      break;
    case 2://删除
      ListDelete(L);
      system("pause");
      break;
    case 3://取值
      GetElem(L);
      system("pause");
      break;
    case 4://查找
      LocateElem(L);
      system("pause");
      break;
    case 5://判断链表是否为空
      ListEmpty(L);
      system("pause");
      break;
    case 6://求单链表的长度
      ListLength(L);
      system("pause");
      break;
    case 7://清空
      ClearList(L);
      system("pause");
      break;
    case 8://销毁
      DestroyList(L);
      system("pause");
      return 0;
      break;
    case 9://打印
      PrintList(L);
      system("pause");
      break;
    case 0:
      cout << "欢迎下次使用!" << endl;//退出
      system("pause");
      return 0;
      break;
    default:
      cout << "菜单序号输入有误!" << endl;
      system("pause");
      break;
    }
  }
  system("pause");
  return 0;
}

以上就是C++数据结构之单链表的实现的详细内容,更多关于C++单链表的资料请关注我们其它相关文章!

(0)

相关推荐

  • C++ 数据结构超详细讲解单链表

    目录 前言 一.链表是什么 链表的分类 二.链表的实现 总结 (❁´◡`❁) 单链表 前言 上篇顺序表结尾了解了顺序表的诸多缺点,链表的特性很好的解决了这些问题,本期我们来认识单链表. 一.链表是什么 链表是一种物理存储结构上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接依次实现的. 由图,链式结构在逻辑上是连续的,但是物理上不一定连续 显示中结点一般是从堆上申请出来的 从堆上申请的空间,是按照一定的策略划分的,两次申请的空间,可能连续,可能不连续,见顺序表 链表的分类 链表

  • C++使用模板实现单链表

    本文实例为大家分享了用模板实现单链表,供大家参考,具体内容如下 话不多说 直接上代码 #include <iostream> using namespace std; template<typename E> class CLink; template<typename T> class Node { friend class CLink<T>; public: /* 构造函数和析构函数一般不加类型参数 本类类中除了构造函数和析构函数以外 其它的地方都要加上

  • C++编程语言实现单链表详情

    目录 一.单链表简单介绍 二.下面我们先实现单链表的初始化. 三.实现单链表的插入与删除数据 一.单链表简单介绍 首先,我们再回顾一下线性表的两种存储方式--顺序存储与链式存储 上图左边为顺序存储,右边为链式存储 之前我们利用数组来实现顺序表,对于顺序表的优点缺点,总结来说就是,查找方便,增删复杂. 线性表之顺序存储的优缺点 而链表特点可以说恰恰相反,增删方便,查找复杂. 今天实现的是链表中最简单的一种--单链表(每个结点中只含有一个指针域) 对于链表我们只知道它每个结点的存储的物理地址是不连续

  • C++数据结构之单链表

    目录 单链表结构的定义 单链表打印 动态申请一个结点 单链表尾插 单链表尾删 单链表头插 单链表头删 求单链表长度 单链表查找 单链表在pos位置插入 单链表在pos后面位置插入 单链表删除pos位置 单链表删除pos的下一个结点 判断单链表是否为空 头文件 源文件 简介: 线性表的顺序存储结构有一个缺点就是插入和删除时需要移动大量元素,这会耗费许多时间.能不能想办法解决呢?干脆所有的元素都不要考虑相邻位置了,哪有空位就到哪里,让每一个元素都知道它下一个元素的位置在哪里.线性表链式存储结构: 用

  • C++实现单链表的构造

    单链表的构造,包括最常用函数,setData(),Insert(),Remove(),getData(),Search(). 代码如下: #include <iostream> #include <stdlib.h> using namespace std; template<class T> struct LinkNode{ T data; LinkNode<T> *link; LinkNode(LinkNode<T> *ptr=NULL){l

  • C++中单链表的建立与基本操作

    准备数据 准备在链表操作中需要用到的变量及数据结构 示例代码如下: 复制代码 代码如下: struct Data   //数据结点类型 { string key;  //关键字  string name; int age;};struct CLType  //定义链表结构 { Data nodeData; Data *nextNode;}; 定义了链表数据元素的类型Data以及链表的数据结构CLType.结点的具体数据保存在一个结构Data中,而指针nextNode用来指向下一个结点. 我们可以

  • C#数据结构之单链表(LinkList)实例详解

    本文实例讲述了C#数据结构之单链表(LinkList)实现方法.分享给大家供大家参考,具体如下: 这里我们来看下"单链表(LinkList)".在上一篇<C#数据结构之顺序表(SeqList)实例详解>的最后,我们指出了:顺序表要求开辟一组连续的内存空间,而且插入/删除元素时,为了保证元素的顺序性,必须对后面的元素进行移动.如果你的应用中需要频繁对元素进行插入/删除,那么开销会很大. 而链表结构正好相反,先来看下结构: 每个元素至少具有二个属性:data和next.data

  • Python数据结构之单链表详解

    本文实例为大家分享了Python数据结构之单链表的具体代码,供大家参考,具体内容如下 # 节点类 class Node(): __slots__=['_item','_next'] # 限定Node实例的属性 def __init__(self,item): self._item = item self._next = None # Node的指针部分默认指向None def getItem(self): return self._item def getNext(self): return s

  • python算法与数据结构之单链表的实现代码

    =一.链表 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域. 相比于线性表顺序结构,操作复杂.由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是

  • Java数据结构之单链表详解

    一.图示 二.链表的概念及结构 链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 . 实际中链表的结构非常多样,以下情况组合起来就有8种链表结构: 单向.双向 带头.不带头 循环.非循环 今天,我们实现的是一个 单向 无头 非循环的链表. 下面是此链表的结构组成. 三.单链表的实现 (1)定义一个节点类型 我们创建一个 ListNode 的类作为节点类型,那么我们如何定义成员属性呢? 通过上面的结构分析,我们需要定义两个成员变量 val --作为该节点的

  • C++数据结构之单链表的实现

    目录 一.单链表的定义 二.单链表的基本操作的实现 1.初始化 2.取值 3.查找 4.插入 5.删除 三.完整代码 四.测试一下代码 一.单链表的定义 线性表的链式存储又称为单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素.为了建立数据元素之间的线性关系,对每个链表结点,除存放元素自身的信息外,还需要存放一个指向其后继的指针. 单链表中结点类型的描述如下: typedef struct LNode{ // 定义单链表节点类型 ElemType data; // 数据域 struct

  • C语言数据结构之单链表的实现

    目录 一.为什么使用链表 二.链表的概念 三.链表的实现 3.1 创建链表前须知 3.2 定义结构体 3.3 申请一个节点 3.4 链表的头插 3.5 链表的尾插 3.6 链表的尾删 3.7 链表的头删 3.8 寻找某节点 3.9 在指定节点前插入节点 3.10 删除指定节点前的节点 3.11 链表的销毁 一.为什么使用链表 在学习链表以前,我们存储数据用的方式就是数组.使用数组的好处就是便于查找数据,但缺点也很明显. 使用前需声明数组的长度,一旦声明长度就不能更改 插入和删除操作需要移动大量的

  • C语言数据结构之单链表与双链表的增删改查操作实现

    目录 前言 单链表的增删改查 定义结构体以及初始化 增加结点 删除结点 查找修改结点 移除结点 最终效果 双链表的基本操作 初始化建表 遍历双链表 指定位置插入结点 指定位置删除结点 查找结点位置 最终效果 结语 前言 上篇博客分享了创建链表传入二级指针的细节,那么今天就分享几个c语言课程实践设计吧.这些程序设计搞懂了的话相当于链表的基础知识牢牢掌握了,那么再应对复杂的链表类的题也就能慢慢钻研了.学习是一个积累的过程,想要游刃有余就得勤学苦练! 单链表的增删改查 (1)项目需求 构造带有头结点的

  • C语言数据结构之单链表存储详解

    目录 1.定义一个链表结点 2.初始化单链表 3.输出链表数据 4.完整代码 如果说,顺序表的所占用的内存空间是连续的,那么链表则是随机分配的不连续的,那么为了使随机分散的内存空间串联在一起形成一种前后相连的关系,指针则起到了关键性作用. 单链表的基本结构: 头指针:永远指向链表第一个节点的位置. 头结点:不存任何数据的空节点,通常作为链表的第一个节点.对于链表来说,头节点不是必须的,它的作用只是为了方便解决某些实际问题. 首元结点:首个带有元素的结点. 其他结点:链表中其他的节点. 1.定义一

  • C语言数据结构之单链表操作详解

    目录 1.插入操作 2.删除操作 3.查找操作 4.修改操作 5.完整代码 1.插入操作 (1)创建一个新的要插入的结点 (2)将新结点的 next 指针指向插入位置后的结点 (3)将插入位置前的节点指针 next 指向新的结点 注意:步骤(2)(3)的顺序不能颠倒,否则会导致插入位置后的部分链表丢失. 插入位置一共分三种,分别是头部插入.中间插入和尾部插入. 如图: 代码: link* insertElem(link* p,int elem,int pos){ link* temp = p;/

随机推荐