花了点时间,手写了链表的常见操作,测试无误
首先注意点:
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;
}
/