数据结构-单向链表 C和C++的实现

数据结构,一堆数据的存放方式。

今天我们学习数据结构中的 链表

数组,大家相当熟悉的存放数据方式,而链表是数组的一种特殊方式,它每个节点包括两个部分:

  • 数据域:存放数据,此部分与数组相同
  • 指针域:存放了下一个节点的地址

链表比数组多了指针域,因为链表需要通过上一个节点的指针域去找下一个数据,比如有一个链表ABCD四个节点,我们要访问D里边的数据。操作如下:

  1. 先通过A节点的指针域找到B节点
  2. 再通过B节点的指针域找到C节点
  3. 再通过C节点的指针域找到D节点
  4. 获取D节点数据域的数据

对比数组直接通过下标访问,链表的访问方式相当麻烦,既然这么麻烦,为什么还有链表这种数据结构呢?因为链表插入删除节点方式十分便捷,在数据量大的时候,删除数组的数据需要把删除数据后面的数据都前移一位,而链表只需要改变前一个元素的指针域,插入和删除操作速度快

这么厉害的东西,还是看程序比较直接

单向链表

C

(此处插入代码)

C++

在C++中,使用模板的方法实现

本程序包括3个文件组成,他们分别是:

定义节点类:Node.h

这个类定义了每个节点的两个区域:m_tpData数据域 和 m_tpNext指针域:

#include <iostream>

using namespace std;

template <typename T>
class Node
{
public:
    Node();
    Node(T data);
    ~Node();
    void setData(T data);
    T getData();
    void setNext(Node<T> *next);
    Node* getNext();
    void printData();
private:
    T *m_tpData;
    Node<T> *m_tpNext;
};

template <typename T>
Node<T>::Node()
{
    m_tpData = new T;
    m_tpNext=NULL;
}

template <typename T>
Node<T>::Node(T data)
{
    m_tpData = new T(data);
    m_tpNext=NULL;
}

template <typename T>
Node<T>::~Node()
{
    delete m_tpData;
    m_tpData=NULL;
}

template <typename T>
void Node<T>::setData(T data)
{
    *m_tpData = data;
}

template <typename T>
T Node<T>::getData()
{
    return *m_tpData;
}

template <typename T>
void Node<T>::setNext(Node<T> *next)
{
    m_tpNext = next;
}

template <typename T>
Node<T>* Node<T>::getNext()
{
    return m_tpNext;
}

template <typename T>
void Node<T>::printData()
{
    cout<<*m_tpData<<endl;
}

链表类 LinkList.h

#include <iostream>
#include "Node.h"

using namespace std;

template <typename T>
class LinkList
{
public:
    LinkList();
    ~LinkList();
    bool isListEmpty();
    bool clearList();
    int getListLength();
    int getElemIndex(T &elem);
    bool getListElem(int index,T* elem);
    //bool getListPrevious(int index,T* elem);
    //bool getListNext(int index,T* elem);
    bool ListInsert(int index,T &elem);
    bool ListDelete(int index,T *elem);
    void ListPrint(void);
private:
    Node<T> *m_pList;
    int m_iLength;
};

template <typename T>
LinkList<T>::LinkList()
{
    m_pList = new Node<T>;
    m_pList->setData(NULL);
    m_pList->setNext(NULL);
    m_iLength=0;
}

template <typename T>
LinkList<T>::~LinkList()
{
    Node<T> *nextNode = m_pList;
    while(nextNode->getNext()!=NULL)    //delete Node while pointerNext == NULL
    {
        nextNode=m_pList->getNext();
        delete m_pList;
        m_pList = nextNode;
    }
    delete m_pList;//delete last Node
    m_pList = NULL;
}

template <typename T>
bool LinkList<T>::isListEmpty()
{
    if(m_iLength==0)
        return true;
    return false;
}

template <typename T>
bool LinkList<T>::clearList()
{
    if(isListEmpty())
    {
        cout<<"List empty clear fail"<<endl;
        return false;
    }

    //delete All node except first node
    Node<T> *nowNode = m_pList->getNext();
    Node<T> *nextNode = m_pList->getNext();
    while(nextNode->getNext()!=NULL)
    {
        nextNode=nowNode->getNext();
        delete nowNode;
        nowNode = nextNode;
    }
    delete nowNode;//delete last Node

    m_iLength = 0;
    m_pList->setNext(NULL);
    return true;
}

template <typename T>
int LinkList<T>::getListLength()
{
    return m_iLength;
}
template <typename T>
int LinkList<T>::getElemIndex(T &elem)
{
    Node<T> *tempNode = m_pList;
    for(int i=0;i<m_iLength;i++)
    {
        tempNode = tempNode->getNext();
        if(elem == tempNode->getData())
        {
            return i;
        }
    }
    return -1;
}
template <typename T>
bool LinkList<T>::getListElem(int index,T* elem)
{
    if(index<0 || index>= m_iLength)
    {
        return false;
    }

    Node<T> *tempNode = m_pList;
    for(int i=0;i<=index;i++)
    {
        tempNode=tempNode->getNext();
    }

    *elem = tempNode->getData();
    return true;
}

template <typename T>
bool LinkList<T>::ListInsert(int index,T &elem)
{
    //index out of range
    if(index<0 || index>m_iLength)
    {
        return false;
    }

    //
    Node<T> *tempPreNode = m_pList;
    for(int i=0;i<index;i++)
    {
        tempPreNode = tempPreNode->getNext();
    }

    Node<T> *newnode = new Node<T>;    //create a new node
    if(newnode == NULL)
    {
        cout<<"new node create fail"<<endl;
        return false;
    }
    Node<T> *tempNode= tempPreNode->getNext();//save pre node pointer
    tempPreNode->setNext(newnode); //set pre node pointer to new node address
    newnode->setNext(tempNode);//set new node pointer to pre node pointer
    newnode->setData(elem);    //set new node new data
    m_iLength++;
    return true;
}

template <typename T>
bool LinkList<T>::ListDelete(int index,T *elem)
{
    //index out of range
    if(index<0 || index>=m_iLength)
    {
        return false;
    }

    //
    Node<T> *tempPreNode = m_pList; //pre node
    for(int i=0;i<index;i++)//find pre node
    {
        tempPreNode = tempPreNode->getNext();
    }

    Node<T> * tempNode = tempPreNode->getNext();//save delete point pointer
    tempPreNode->setNext(tempNode->getNext());//set pre node  point to next node
    *elem = tempNode->getData();
    delete tempNode;

    m_iLength--;
    return true;
}

template <typename T>
void LinkList<T>::ListPrint(void)
{
    if(isListEmpty())
    {
        cout<<"List empty"<<endl;
        return;
    }
    Node<T> *tempNode=m_pList->getNext();
    while(tempNode->getNext() != NULL)
    {
        tempNode->printData();
        tempNode = tempNode->getNext();
    }
    tempNode->printData();
    cout<<"end"<<endl;
}

单项链表模板定义完了,我们在main.cpp中使用int类型实例化它、并测试它的功能

#include <iostream>
#include <string>
#include "LinkList.h"
using namespace std;

int main(void)
{
    /*insert data check*/
    int data[10]={0,1,2,3,4,5,6,7,8,9};
    LinkList<int> *linklist = new LinkList<int>;
    for(int i=0;i<5;i++)
    {
        linklist->ListInsert(i,data[i]);
    }
    linklist->ListPrint();

    /*getElemIndex check*/
    cout<<"getElemIndex:"<<linklist->getElemIndex(data[4])<<endl;

    /*getListElem check*/
    int getdata;
    linklist->getListElem(2,&getdata);
    cout<<"getListElem:"<<getdata<<endl;

    /*delete data check*/
    int deletedata;
    linklist->ListDelete (0,&deletedata);
    cout<<"delete data:"<<deletedata<<endl;
    linklist->ListPrint();

    /*clearList check*/
    linklist->clearList();
    linklist->ListPrint();

    delete linklist;
    linklist = NULL;
    system("pause");
    return 0;
}

运行结果如下:

时间: 2024-08-02 06:58:01

数据结构-单向链表 C和C++的实现的相关文章

数据结构:单向链表系列6--交换相邻两个节点1(交换数据域)

给定一个单向链表,编写函数交换相邻 两个元素 输入: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 输出: 2 -> 1 -> 4 -> 3 -> 6 -> 5 -> 7 输入: 1 -> 2 -> 3 -> 4 -> 5 -> 6 输出: 2 -> 1 -> 4 -> 3 -> 6 -> 5 通过观察发现:当输入的与元素个数是单数的时候,最后一位不参与交换

数据结构--单向链表

C语言中,我们在使用数组时,会需要对数组进行插入和删除的操作,这时就需要移动大量的数组元素,但在C语言中,数组属于静态内存分配,数组在定义时就必须指定数组的长度或者初始化.这样程序一旦运行,数组的长度就不能再改变,若想改变,就只能修改源代码.实际使用中数组元素的个数也不能超过数组元素的最大长度,否则就会发生下标越界的错误(这是新手在初学C语言时肯定会遇到的问题,相信老师也会反复强调!!!但这种问题肯定会遇到,找半天找不到错误在哪,怪我咯???).另外如果数组元素的使用低于最大长度,又会造成系统资

数据结构-单向链表相关算法

#include <stdio.h>#include <stdlib.h>#define OVERFLOW -2#define OK 1#define ERROR 0typedef int ElemType;//单向链表结构体typedef struct LNode {    ElemType data;    struct LNode *next;}LNode,*LinkList; LinkList CreateList_L(LinkList L,int n);void Trav

数据结构:单向链表(Linked List)

本文来源: Linked List | Set 1 (Introduction) Linked List | Set 2 (Inserting a node) Linked List | Set 3 (Deleting a node) Find Length of a Linked List (Iterative and Recursive) (todo:在结构中保持节点数信息) Search an element in a Linked List (Iterative and Recursiv

数据结构:单向链表系列5--在链表中查找元素

在链表中查找元素 函数签名: bool search(Node *head, int x) 如果在链表中查找到这个元素返回true,否则false 迭代法 2) 初始化一个节点指针, current = head. 3) 如果current不为NULL执行以下循环 a) current->key 等于当前待查找值key则返回true. b) current = current->next 4) 否则返回 false /*Checks whether the value key is prese

数据结构:单向链表系列8--反转链表

业务需求:给定一个指向头指针的链表,反转链表.实现过程:更改相邻节点之间的链域. 例: 输入: 1->2->3->4->NULL输出:4->3->2->1->NULL 输入:1->2->3->4->5->NULL输出:5->4->3->2->1->NULL 输入: NULL输出: NULL 输入: 1->NULL输出: 1->NULL 迭代法: 空间复杂度:O(1),时间复杂度:O(n)

Python3中定义一个单向链表

链表是由节点构成的,一个指针代表一个方向,如果一个构成链表的节点都只包含一个指针,那么这个链表就是单向链表. 单向链表中的节点不光有代表方向的指针变量,也有值变量.所以我们定义链表,就是要定义链表中的节点,对链表的操作最后也就是对节点的操作. 这些包含数据的节点们在一种指定的结构下连接起来,成为了一种数据结构——单向链表.以上是我对单向链表的理解. 以下是我用python3对单向链表这种数据结构的一种实现: ''' Python3版单向链表-单向链表简称单链表 单链表中所包含的基本操作: 初始化

数据结构之链表单向操作总结

链表是数据结构的基础内容之一,下面就链表操作中的创建链表.打印链表.求取链表长度.判断链表是否为空.查找结点.插入结点.删除结点.逆转链表.连接链表.链表结点排序等进行总结. 1.创建表示结点的类,因为链表操作中需要比较结点,因此结点需要实现comparable接口. public class Node implements Comparable<Node> { private Object data; private Node next; //构造函数 public Node() { thi

数据结构与算法-单向链表

概述 由于最近在工作中需要用到树形结构来解决一些问题,所以萌生了系统学习“数据结构和算法”的想法,于是乎从最简单的表结构开始.由于数组是最简单的表结构的实现,也是各个编程语言内置的数据类型,所以不做更多的记录.表结构中以下实现打算学习: LinkedList Stack Queue HashTable Dictionary 本篇为学习数据结构的第一篇随笔,从最简单的单向链表开始吧. 实现(C#) 平台:dotNet Core 1.0, C# IDE:VSCode 如果考虑算法复用的话,可以实现泛