手写 线性链表的各种操作

花了点时间,手写了链表的常见操作,测试无误

首先注意点:

1 头结点不算第一个节点,且链表长度不包含头结点

2   开始节点默认是 头结点后的第一个节点,且 下标为0,

3 函数里第i个节点,是从下标为0的节点开始数,数到 第i个。

以下函数,皆是用上述标准 定义的

定义了 Node类和 List类。 2个类的各文件如下

Node.h

#pragma once
class Node
{
public:
    Node(void);
    ~Node(void);

    int data;
    Node* next;

    void PrintNode();
};

/

Node.cpp

#include "stdafx.h"
#include "Node.h"

#include <iostream>

using namespace std;

Node::Node(void)
{
}

Node::~Node(void)
{
}

void Node::PrintNode()
{
    cout<<data<<endl;
}

//

List.h

#pragma once

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

class List
{
public:
    List(void);
    ~List(void);

    List(int size);

    bool ListIsEmpty();
    int ListLength();//  求链表的长度,且不包含头结点
    void ClearList();    
    

   //链表尾部插入
    bool ListInsertTail(Node* head, int data);
    bool ListInsertTail(int data);
    bool ListInsertTail(Node* pNode);

//头部插入

    bool ListInsertHead(Node *pNote);
    bool ListInsertHead(int data);
    
    bool ListInsert(Node *pNote,int pos);

    bool ListDelete(int i, Node* pNode);

 

//获取指定节点的前驱节点

    bool GetPriorNode(Node *pCurrentNode, Node* pPreNode);

//获取指定节点的后驱节点
    bool GetNextNode(Node *pCurrentNode, Node* pNextNode);

//遍历整个链表

    void ListTraverse();

//获取指定节点

    bool GetElem(int i,Node *pNote);

    int LocateElem(Node *pNote);

//获取头结点

    Node* GetHead();

//打印所有节点

    void PrintAll();

private:
    Node * m_phead;//头结点
    int m_iLength;// 链表的长度,且不包含头结点

//

List.cpp

 

// list.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "List.h"
#include <iostream>

using namespace  std;
List::List(void)
{
    m_phead = new Node; 

   m_phead->data = 0;   
    m_phead->next = NULL;
    m_iLength = 0;
}


List::List(int size)
{

}

bool List::ListIsEmpty()
{
    if(m_iLength == 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}

int List::ListLength()
{
    return m_iLength;
}

//清除其他节点,只保留头结点一个
void List::ClearList()
{
    Node* CurrentNode = m_phead->next;
    
    while (CurrentNode !=NULL)
    {
        Node * temp = CurrentNode->next;
        delete CurrentNode;
        CurrentNode = temp;
    }
    m_phead->next = NULL;
    m_iLength = 1;
}

//用构造函数初始化链表完毕后,用此函数构造链表其他节点 ,data是新插入节点的值
//使用尾插入法,每个新节点都接在最后一个节点的后面
bool List::ListInsertTail(Node* head, int data)
{
    assert(head);
    Node* pNew = new  Node;
    pNew->data = data;
    //可能链表只有一个头结点没有其他节点, 新节点直接 接在头结点后面
    if ( head->next == NULL)
    {        
        head->next = pNew;
        m_iLength++;
        return true;
    }
    else
    {
        //不为空就 遍历链表,找到最后一个节点,把新节点接在 后面
        //用一个临时节点作为 指向标志,从头节点开始遍历,当为Null就是找到了最后一个节点了, 然后指向新节点
        Node* pCur = head;
        while (pCur->next)
        {

            pCur = pCur->next;
        }
        pCur->next = pNew;
        m_iLength++;

        return true;
    }
    return false;
}

//尾插法 建立链表
bool List::ListInsertTail(int data)
{
    //assert(head);
    Node* pNew = new  Node;
    pNew->data = data;
    //可能链表只有一个头结点没有其他节点, 新节点直接 接在头结点后面
    if ( m_phead->next == NULL)
    {        
        m_phead->next = pNew;
        m_iLength++;
        return true;
    }
    else
    {
        //不为空就 遍历链表,找到最后一个节点,把新节点接在 后面
        //用一个临时节点作为 指向标志,从头节点开始遍历,当为Null就是找到了最后一个节点了, 然后指向新节点
        Node* pCur = m_phead;
        while (pCur->next)
        {

            pCur = pCur->next;
        }
        pCur->next = pNew;
        m_iLength++;
        return true;
    }
    return false;
}

//尾插法 建立链表
bool List::ListInsertTail(Node* pNode)
{
    //assert(head);
    Node* pNew = new  Node;
    if (pNew==NULL)
    {
        return false;
    }
    pNew->data = pNode->data;
    //可能链表只有一个头结点没有其他节点, 新节点直接 接在头结点后面
    if ( m_phead->next == NULL)
    {        
        m_phead->next = pNew;
        m_iLength++;
        return true;
    }
    else
    {
        //不为空就 遍历链表,找到最后一个节点,把新节点接在 后面
        //用一个临时节点作为 指向标志,从头节点开始遍历,当为Null就是找到了最后一个节点了, 然后指向新节点
        Node* pCur = m_phead;
        while (pCur->next != NULL)
        {
            pCur = pCur->next;
        }
        pCur->next = pNew;
        //新节点成为最后一个节点了。那么为了规范,新节点的next设置为Null
        pNew->next = NULL;
        m_iLength++;
        return true;
    }
    return false;
}

//新节点插入到头结点的后面,头插法(逆序构造链表), 这种插入完成后,是倒过来的
//比如说 插入12345,每一个都插入到head的后, 完成后是  head 4,3,2,1
bool List::ListInsertHead(Node *pNote)
{    

    Node* newNode = new Node;
    if (newNode == NULL)
    {
        return false;
    }
    else
    {
        newNode->data = pNote->data;
        newNode->next = m_phead->next;
        m_phead->next = newNode;
        m_iLength++;
    }
    return true;
}
//同上
bool List::ListInsertHead(int data)
{

    Node* newNode = new Node;
    if (newNode == NULL)
    {
        return false;
    }
    else
    {
        newNode->data = data;
        newNode->next = m_phead->next;
        m_phead->next = newNode;
        m_iLength++;
    }
    return true;
}

/*在第pos个节点的前面插入,注意计算链表长度,头结点不算在内,长度从头结点的下一个节点开始算第一个节点,
且这个节点的下标为0, 插入的时候,pos表示下标,pos是0则是在头结点后面插入,pos==m_iLength,则插在最后面
参数pos表示从头结点的下一个节点开始算第0个节点 然后一直数到第i个节点。新节点插入到第i位,原值往后推一位
*/
bool List::ListInsert(Node *pNode,int pos)
{
    if (pos == 0)
    {
        ListInsertHead(pNode);
        return true;
    }
    else if (pos == m_iLength)
    {
        ListInsertTail(pNode);
        return true;
    }
    else
    {
        Node* pCur = m_phead;        
        for (int k = 0 ; k < pos;k ++)
        {
            pCur = pCur->next;
        }
        Node* pNew = new Node;
        pNew->data = pNode->data;

        pNew->next = pCur->next;
        pCur->next = pNew;
        m_iLength++;

        return true;
        
    }
    return false;
}

//同上,也是删除 指定第pos位的节点
bool List::ListDelete(int i, Node* pNode)
{
    if (i >= 0 || i< m_iLength)
    {
        Node* pCur = m_phead;
        Node* pCurBefore = NULL;

        int maxlen = m_iLength;
        for (int k = 0; k <= i; k++)
        {
            pCurBefore = pCur;
            pCur = pCur->next;
        }

        pNode->data = pCur->data;
        pCurBefore->next = pCurBefore->next->next;

        delete pCur;
        pCur = NULL;
        m_iLength--;
        return true;
    }
    else
    {
        return false;
    }
}

//获取指定节点的前一个节点
bool List::GetPriorNode(Node *pCurrentNode, Node* pPreNode)
{
    Node* pCur = m_phead;
    Node* pNodeBefor = NULL;
    while (pCur->next != NULL)
    {        
        pNodeBefor = pCur;
        pCur = pCur->next;
        if (pCur->data == pCurrentNode->data)
        {    
            //上一个节点竟然是 头结点,那就是没有前驱节点
            if (pNodeBefor == m_phead)
            {
                return false;
            }
            else
            {
                pPreNode->data = pNodeBefor->data;
                return true;
            }            
        }
    }
    return false;
}

bool List::GetNextNode(Node *pCurrentNode, Node* pNextNode)
{
    Node* pCur = m_phead;    
    while (pCur->next != NULL)
    {    
        pCur = pCur->next;
        if (pCur->data == pCurrentNode->data)
        {    
            //判断当前节点是不是最后一个节点,最后一个节点没有后驱节点
            if (pCur->next == NULL)
            {
                return false;
            }
            else
            {
                pNextNode->data = pCur->next->data;
                return true;
            }
            
        }
    }
    return false;
}

void List::ListTraverse()
{
    Node* pCur = m_phead;
    while (pCur->next != NULL)
    {
        pCur = pCur->next;
        pCur->PrintNode();
    }
}

//根据位置pos 找节点,用pNote把值带回来
bool List::GetElem(int pos, Node *pNote)
{
    if (pos < 0 || pos >= m_iLength)
    {
        return false;
    }

    Node* pCur = m_phead;
    Node* pCurBefore = NULL;

    int maxlen = m_iLength;
    for (int k = 0; k <= pos; k++)
    {
        pCurBefore = pCur;
        pCur = pCur->next;
    }

    pNote->data = pCur->data;

    return true;

}
//从头结点开始遍历,根据节点 返回 pos也就是位置的值
int List::LocateElem(Node *pNote)
{

    Node* pCur = m_phead;
    Node* pCurBefore = NULL;

    int pos = 0;
    while (pCur->next != NULL)
    {
        pCur = pCur->next;        
        if (pCur->data == pNote->data)
        {            
            return pos;
        }
        pos++;
    }
    return -1;

}

Node* List::GetHead()
{
    return m_phead;
}

void List::PrintAll()
{
    Node* pCur = m_phead;
    
    while (pCur->next != NULL)
    {
        pCur = pCur->next;
        cout<<pCur->data;
        cout<<" ";
        pCur= pCur->next; 
    }
}

List::~List(void)
{
    ClearList();
    delete m_phead;
    m_phead = NULL;
}

 

 

/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值