服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++详解如何实现单链表

C++详解如何实现单链表

2023-02-14 15:27肩上风骋 C/C++

线性表的链式存储又称为单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素。本文将用C++实现单链表,需要的可以参考一下

单链表

链表内存空间不一定连续,其扩展性较好。多余的不多说了。该文主要记录单链表的实现,该单链表含有一个非空的头节点。链表的操作实际上是对其指针域与数据域的操作。

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

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

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

单链表的基本操作

1.初始化

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

具体代码:

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

2.取值

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

具体代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
// 单链表的取值
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进行比较,返回查找结果。

具体代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//单链表的查找
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.插入

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 单链表的插入
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.删除

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//单链表的删除
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;
}

示例代码

直接上代码:

LinkList.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#pragma once
typedef struct LINKLIST {
    void * data;
    struct LINKLIST *pNext;
}LinkList;
typedef void(*PrintLinkList)(void *);
//无头的链表
class LinkNode
{
public:
    LinkNode();
    ~LinkNode();
    void insertLinkList(int pos,void * data);
    void removeByPosInLinkList(int pos);
    int getSizeLinkList();
    int findValueInLinkList(void* value);
    LinkList* getFirstNodeLinkList();
    void printLinkList(PrintLinkList print);
private:
    LinkList *m_pHead;
    int m_size;
};

LinkList.cpp

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// LinkList.cpp
//
#include "LinkList.h"
#include <iostream>
using namespace std;
LinkNode::LinkNode()
{
    m_pHead = new LinkList;
    m_pHead->data = nullptr;
    m_pHead->pNext = nullptr;
    m_size = 0;
}
LinkNode::~LinkNode()
{
    if (m_pHead != nullptr)
    {
        while (m_pHead != nullptr)
        {
            LinkList *pNext = m_pHead->pNext;
            delete m_pHead;
            m_pHead = nullptr;
            m_pHead = pNext;
        }
    }
}
void LinkNode::insertLinkList(int pos, void * data)
{
    if (m_pHead == nullptr)
    {
        return;
    }
    if (data == nullptr)
    {
        return;
    }
    //插入位置矫正
    if (pos < 0 || pos > m_size )
    {
        pos = m_size;
    }
    LinkList * insertNode = new LinkList;
    insertNode->data = data;
    insertNode->pNext = nullptr;
    //找到前一个位置(pos从0开始)
    LinkList *pPre = m_pHead;
    for (int i = 0; i < pos; ++i)
    {
        pPre = pPre->pNext;
    }
    //有头节点的链表
    insertNode->pNext = pPre->pNext;
    pPre->pNext = insertNode;
    m_size++;
}
void LinkNode::removeByPosInLinkList(int pos)
{
    if (m_pHead == nullptr)
    {
        return;
    }
    if (pos < 0 || pos >= m_size)
    {
        return ;
    }
    //找到前一个位置(pos从0开始)
    LinkList *pPre = m_pHead;
    for (int i = 0; i < pos; ++i)
    {
        pPre = pPre->pNext;
    }
    LinkList *delNode = pPre->pNext;
    pPre->pNext = delNode->pNext;
    delete delNode;
    delNode = nullptr;
    m_size--;
}
int LinkNode::getSizeLinkList()
{
    return m_size;
}
int LinkNode::findValueInLinkList(void* value)
{
    int nPos = -1;
    if (m_pHead == nullptr)
    {
        return nPos;
    }
    if (value == nullptr)
    {
        return nPos;
    }
    LinkList *pHead = m_pHead;
    for (int i = 0; i < m_size; ++i)
    {
        //有空的头节点
        pHead = pHead->pNext;
        if (pHead->data == value)
        {
            nPos = i;
            break;
        }
    }
    return nPos;
}
LinkList * LinkNode::getFirstNodeLinkList()
{
    if (m_pHead == nullptr)
    {
        return nullptr;
    }
    return m_pHead->pNext;//有空的头节点
}
void LinkNode::printLinkList(PrintLinkList print)
{
    if (m_pHead == nullptr)
    {
        return ;
    }
    //不能直接移动头节点,需要保留头节点
    LinkList *pTemp = m_pHead;
    pTemp = pTemp->pNext;
    while (pTemp != nullptr)
    {
        print(pTemp->data);
        pTemp = pTemp->pNext;
    }
    cout << endl;
}

mian.cpp

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include "LinkList.h"
using namespace std;
typedef struct PERSON {
    char name[64];
    int age;
    int score;
}Person;
void myPrint(void *data)
{
    Person *p = (Person*)data;
    cout << "name : " << p->name << " age: " << p->age << " score: " << p->score << endl;
}
void test()
{
    LinkNode *plinkList = new LinkNode;
    Person p1 = {"husdh",23,78};
    Person p2 = { "hudfs",23,98 };
    Person p3 = { "术后",23,78 };
    Person p4 = { "喀什",23,67 };
    plinkList->insertLinkList(0, &p1);
    plinkList->insertLinkList(1, &p2);
    plinkList->insertLinkList(2, &p3);
    plinkList->insertLinkList(3, &p4);
    plinkList->printLinkList(myPrint);
    cout <<"链表的节点数: "<< plinkList->getSizeLinkList() << endl;
    plinkList->removeByPosInLinkList(1);
    cout << "remove" << endl;
    plinkList->printLinkList(myPrint);
    cout << "删除后链表的节点数: " << plinkList->getSizeLinkList() << endl;
    cout << "p3位置: " << plinkList->findValueInLinkList(&p3) << endl;
    myPrint(plinkList->getFirstNodeLinkList()->data);
    delete plinkList;
    plinkList = nullptr;
}
int main()
{
    test();
    return 0;
}

以上是单链表实现及测试代码。

开发环境

vs2017控制台输出程序。

运行结果

C++详解如何实现单链表

以上仅记录,方便理解。

到此这篇关于C++详解如何实现单链表的文章就介绍到这了,更多相关C++单链表内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/blqzj214817/article/details/125316408

延伸 · 阅读

精彩推荐
  • C/C++C语言实现最大间隙问题实例

    C语言实现最大间隙问题实例

    这篇文章主要介绍了C语言实现最大间隙问题的方法,是一个比较经典的算法设计问题,对于学习算法设计有一定的借鉴价值,需要的朋友可以参考下...

    C语言程序设计7872021-02-02
  • C/C++餐馆点菜系统C语言源代码

    餐馆点菜系统C语言源代码

    这篇文章主要为大家详细介绍了餐馆点菜系统C语言源代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    gp13141127092021-08-05
  • C/C++memset函数的使用分析

    memset函数的使用分析

    本篇文章是对memset函数的使用进行了详细的分析介绍,需要的朋友参考下...

    C语言教程网5252020-12-15
  • C/C++C语言判断一个数是否是2的幂次方或4的幂次方

    C语言判断一个数是否是2的幂次方或4的幂次方

    本文中我们来看一下如何用C语言判断一个数是否是2的幂次方或4的幂次方的方法,并且判断出来是多少次方,需要的朋友可以参考下...

    C语言中文网7042021-04-05
  • C/C++C语言和Python语言有什么区别呢?

    C语言和Python语言有什么区别呢?

    最近几年python语言非常受大家欢迎,所以我也想学习了解下python语言,但是学习之前总是有很多疑问。 因为我现在只会汇编和 C语言 ,所有我想在学习它之...

    永不低头的菜鸟4122020-10-14
  • C/C++C/C++实现俄罗斯方块游戏

    C/C++实现俄罗斯方块游戏

    这篇文章主要介绍了如何利用C/C++实现经典游戏之一的俄罗斯方块,文中的实现步骤讲解详细,对我们学习C语言和C++有一定的帮助,需要的可以参考一下...

    霸道小明11142022-09-24
  • C/C++C++ lambda 捕获模式与右值引用的使用

    C++ lambda 捕获模式与右值引用的使用

    这篇文章主要介绍了C++ lambda 捕获模式与右值引用的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友...

    WolfcsTech5552021-08-27
  • C/C++C++在C语言基础之上增强的几个实用特性总结

    C++在C语言基础之上增强的几个实用特性总结

    这篇文章主要介绍了C++在C语言基础之上增强的几个实用特性总结,包括C++中更强的类型约束以及结构体方面等一些更加高级的特性,需要的朋友可以参考下...

    YoferZhang11982021-03-27