C++ 链表,链表各种方法实现原理

简介: C++ 链表,链表各种方法实现原理

我们在上一章节中讲解到了C++vector容器以及vector容器的各种方法实现原理,我们在这一章节讲解一下链表以及链表的各种方法操作原理。

数组为我们在编程的时候提供了很大的便利,但是有时候我们定义的数组不能满足我们的需求,我们需要一个可变数组来存储我们的数据,我们存储多大数据,就为我们分配多少内存空间,这时候链表就显得尤为重要了。

链表的内部结构其实很简单,就是定义一个结构体,该结构体内不仅存储了我们需要的数据,而且存储了下一个结构的指针,通过指针,让各个元素连接起来,这就是链表。这里给出一张图帮助大家理解

链表实现源码

这里给出链表的各种方法实现源码,源码中注释写得很清楚,相信大家能够理解:

#include <iostream>
#include<windows.h>
using namespace std;
#define success 1
#define error 0
template <class T_ELE>
class LinkedList{
public:
  LinkedList();
  ~LinkedList();
  bool IsEmpty();     //判断链表是否为空
  DWORD clear();      //清空链表
  DWORD GetElement(IN DWORD dwIndex,OUT T_ELE& Element);       //根据索引获取元素
  DWORD GetElementIndex(IN T_ELE&Element);     //根据内容获取索引
  DWORD Insert(IN T_ELE& Element);        //在链表尾部新增元素
  DWORD Insert(IN DWORD dwIndex,IN T_ELE& Element);   //在指定位置插入元素
  DWORD Delete(IN DWORD dwIndex);    //根据索引删除元素
  DWORD GetSize();   //获取链表中元素的数量
private:
  typedef struct _NODE{
    T_ELE Data;    //链表数据
    _NODE* pNext;  //下一个数据指针
  }NODE,*PNODE;
private:
  PNODE m_pList;    //链表头指针
  DWORD m_dwLength; //当前链表元素数量 
};
//无参构造函数,初始化成员 
template <class T_ELE>
LinkedList<T_ELE>::LinkedList()
:m_pList(NULL),m_dwLength(0){
  cout<<"构造函数完成。"<<endl;
}
//析构函数
template <class T_ELE>
LinkedList<T_ELE>::~LinkedList(){
  clear();
  cout<<"析构函数完成。"<<endl;
}
//判断链表是否为空 
template <class T_ELE>
bool LinkedList<T_ELE>::IsEmpty(){
  if((m_dwLength = 0 || m_dwLength) = 0){
    cout<<"链表为空!"<<endl;
    return error;
  }else{
    cout<<"链表不为空,将继续执行。"<<endl;
    return success; 
  }
}
//链表尾部新增节点
template <class T_ELE>
DWORD LinkedList<T_ELE>::Insert(IN T_ELE& Element){
  PNODE pNewNode = new NODE;
  memset(pNewNode,0,sizeof(NODE));
  memcpy(pNewNode,&Element,sizeof(T_ELE));
  pNewNode->pNext = 0;
  //判断列表是否为空,如果为空,则从0新增元素
  PNODE ptemp = m_pList;
  if(IsEmpty()){
    m_pList = pNewNode;
    m_dwLength++;
    return success;
  }else{
    for(int i = 0;i < m_dwLength-1;i++){
      ptemp = ptemp->pNext;
      if(ptemp = NULL){
        cout<<"检测本结构下一个指针为0"<<endl;
      }
    }
  }
  ptemp->pNext = pNewNode;
  m_dwLength++;
  cout<<"表尾新增节点成功。"<<endl;
}
//新增节点到指定位置
template <class T_ELE>
DWORD LinkedList<T_ELE>::Insert(IN DWORD dwIndex,IN T_ELE& Element){
  PNODE pNewNode = new NODE;
  memset(pNewNode,0,sizeof(NODE));
  memcpy(pNewNode,Element,sizeof(T_ELE));
  pNewNode->pNext = 0;
  //判断链表是否为空,如果指针为空,并且Index为0,将在0的位置新增 
  if(IsEmpty){
    m_pList =  pNewNode;
    m_dwLength++;
    return success;
    cout<<"在索引值为0的位置新增元素成功。"<<endl; 
  }
  //判断索引值是否有效
  if(dwIndex < 0 || dwIndex>m_dwLength){
    cout<<"索引值无效!"<<endl;
    return error;
  }
  //如果索引值为0,则将链表头指针指向new的内存,并且将pNext指向原来索引值为0的元素
  pNewNode->m_List;
  m_pList = pNewNode;
  m_dwLength++;
  return success;
  //如果索引值为表尾
  if(dwIndex = m_dwLength){
    Insert(Element);
    return success; 
  }
  //如果索引在链表中
  PNODE ptemp = m_pList;
  for(int i = 0;i < dwIndex-1;i++){
    ptemp = ptemp->pNext;
  }
  pNewNode->pNext = ptemp->pNext;
  ptemp->pNext = pNewNode;
  cout<<"在"<<dwIndex<<"的位置新增元素成功。"<<endl; 
}
//根据索引删除元素
template <class T_ELE>
DWORD LinkedList<T_ELE>::Delete(IN DWORD dwIndex){
  //如果索引为0
  m_pList = m_pList->pNext;
  delete m_pList;
  m_dwLength--; 
  cout<<"删除索引为0的元素已删除。"<<endl;
  //如果索引不为0
  //判断索引是否有效
  if(dwIndex<0 || dwIndex>m_dwLength){
    cout<<"索引"<<dwIndex<<"无效!"<<endl;
    return error;
  }
  //如果索引为链表尾部
   if(dwIndex = m_dwLength){
    PNODE ptemp;
    for(int i = 0;i<dwIndex - 1;i++){
      ptemp = ptemp->pNext;
     }
     delete ptemp->pNext;
     ptemp->pNext = 0;
     cout<<"索引"<<dwIndex<<"元素已删除。"<<endl;
   }
  //如果索引为链表中间位置 
  PNODE ptemp1= m_pList;
  for(int i = 0;i<dwIndex-1;i++){
    ptemp1 = ptemp1->pNext;
  }
  PNODE ptemp2 = ptemp1->pNext;
  ptemp1->pNext = ptemp2->pNext;
  delete ptemp2;
  m_dwLength--;
  cout<<"索引"<<dwIndex<<"的元素已删除。"<<endl;
  return success;
}
//获取链表中元素数量
template <class T_ELE>
DWORD LinkedList<T_ELE>::GetSize(){
  cout<<"当前链表元素个数为"<<m_dwLength<<endl;
  return m_dwLength;
}
//清除链表元素
template <class T_ELE>
DWORD LinkedList<T_ELE>::clear(){
  PNODE ptemp1 = m_pList;
  PNODE ptemp2 = NULL;
  for(int i = 0;i < m_dwLength;i++){
    ptemp2 = ptemp1->pNext;
    delete ptemp1;
  }
} 
//测试函数
void Test(){
  LinkedList<int> v1;
  int a=5;
  v1.Insert(a);
  } 
int main(){
  Test();
  return 0;
}
相关文章
|
1月前
|
存储 Java C++
C++ 引用和指针:内存地址、创建方法及应用解析
C++中的引用是现有变量的别名,创建时需用`&`运算符,如`string &meal = food;`。指针存储变量的内存地址,使用`*`创建,如`string* ptr = &food;`。引用必须初始化且不可为空,而指针可初始化为空。引用在函数参数传递和提高效率时有用,指针适用于动态内存分配和复杂数据结构操作。选择使用取决于具体需求。
41 9
|
2月前
|
C++
【链表】还不会用C++实现链表?一文教会你各种链表的实现
【链表】还不会用C++实现链表?一文教会你各种链表的实现
|
12天前
|
C++
【C++】一文深入浅出带你参透库中的几种 [ 智能指针 ]及其背后实现原理(代码&图示)
【C++】一文深入浅出带你参透库中的几种 [ 智能指针 ]及其背后实现原理(代码&图示)
|
15天前
|
监控 API 数据安全/隐私保护
屏幕监控软件开发指南:C++实现原理解析
在当今数字化时代,屏幕监控软件成为了企业管理和个人隐私保护的重要工具。本文将深入探讨如何使用C++语言实现屏幕监控软件,并解析其实现原理。我们将通过多个代码示例来说明其工作方式,最后将介绍如何将监控到的数据自动提交到网站。
62 3
|
20天前
|
C++
【C++】std::string 转换成非const类型 char* 的三种方法记录
【C++】std::string 转换成非const类型 char* 的三种方法记录
7 0
|
25天前
|
数据安全/隐私保护 C++
C++ 类方法解析:内外定义、参数、访问控制与静态方法详解
C++ 中的类方法(成员函数)分为类内定义和类外定义,用于操作类数据。类内定义直接在类中声明和定义,而类外定义则先在类中声明,再外部定义。方法可以有参数,访问权限可通过 public、private 和 protected 控制。静态方法与类关联,不依赖对象实例,直接用类名调用。了解这些概念有助于面向对象编程。
16 0
|
1月前
|
编译器 C++
C++ 解引用与函数基础:内存地址、调用方法及声明
C++ 中的解引用允许通过指针访问变量值。使用 `*` 运算符可解引用指针并修改原始变量。注意确保指针有效且不为空,以防止程序崩溃。函数是封装代码的单元,用于执行特定任务。理解函数的声明、定义、参数和返回值是关键。函数重载允许同一名称但不同参数列表的函数存在。关注公众号 `Let us Coding` 获取更多内容。
138 1
|
1月前
|
算法 编译器 C++
【C++】C++代码性能优化的方法(全网最适用)
【C++】C++代码性能优化的方法(全网最适用)
|
1月前
|
存储 缓存 C++
C++链表常用的函数编写(增查删改)内附完整程序
C++链表常用的函数编写(增查删改)内附完整程序
|
2月前
|
存储 算法 数据管理
C++中利用随机策略优化二叉树操作效率的实现方法
C++中利用随机策略优化二叉树操作效率的实现方法
77 1