1、单向链表:必要属性 头指针指针, 元素的实际长度, 结构体:数据、指向下一节点的指针
2、操作方法:
//判断链表是否为空
//清空链表
//返回链表的长度
//获取索引处元素内容
//获取指定内容的第一个元素的位置
//插入一个节点
//删除一个节点
#include <stdlib.h>
#include <windows.h>
#include <iostream>
template<class Type>
class CLinkList
{
public:
typedef struct _NODE
{
Type nData;
_NODE * pNext;
}NODE, *PNODE;
public:
CLinkList():m_nHead(nullptr),m_nLen(0)
{
}
~CLinkList()
{
}
public:
//判断链表是否为空
bool LListIsEmpty()
{
return (m_nLen == 0|| m_nHead==nullptr ) ? true : false;
}
//清空链表
void LListCls()
{
//如果头指针不为空 或者 长度不为0 则进行清空链表
if (m_nHead != nullptr || m_nLen != 0)
{
//记录当前指针变量
PNODE temp = m_nHead;
while(temp->pNext)
{
//将头指针后移
m_nHead = temp->pNext;
delete temp;
temp = nullptr;
//将新的头指针赋给临时变量
temp = m_nHead;
}
//删除最后一个节点 并将长度设置为0
delete m_nHead;
m_nHead = nullptr;
m_nLen = 0;
}
}
//返回链表的长度
int LListLen()
{
return m_nLen;
}
//获取索引处元素内容
bool LListGetEle(_In_ int idx, _Out_ Type &type)
{
//判断参数
if (idx<0 || idx>m_nLen)
{
return false;
}
//判断是否为空
if (m_nHead == nullptr || m_nLen == 0)
{
return false;
}
//遍历到要寻找的位置 从0开始 到idx前一个节点 就可以获取到idx中的内容
PNODE temp = m_nHead;
for (int i=0; i<idx; i++)
{
temp = temp->pNext;
}
//将内容传出
memcpy_s(&type, sizeof(Type), &(temp->nData), sizeof(Type));
return true;
}
//获取指定内容的第一个元素的位置
int LListGetIdx(_In_ Type data)
{
//判断是否为空
if (LListIsEmpty())
{
return -1;
}
//遍历 获取所在的位置
PNODE temp = m_nHead;
for (int i=0; i<m_nLen; i++)
{
//比较内容
if (!memcmp(&data, &temp->nData, sizeof(Type)))
{
return i;
}
temp = temp->pNext;
}
return -1;
}
//插入一个节点
bool LListInsert(_In_ int idx, _In_ Type data)
{
// 判断参数
if (idx < 0 || idx > m_nLen)
{
return false;
}
//判断头结点是否为空
if (!m_nHead)
{
m_nHead = new NODE;
m_nHead->nData = data;
m_nHead->pNext = nullptr;
m_nLen++;
return true;
}
//找到要插入的节点
PNODE temp = new NODE;
temp->nData = data;
temp->pNext = nullptr;
//判断是否在头节点处插入
if (idx == 0)
{
//将该节点的pNext 指向 当前的头指针
temp->pNext = m_nHead;
//将头指针指向头节点
m_nHead = temp;
//长度自增
m_nLen++;
return true;
}
//插入的是非头结点
//记录头指针
PNODE pre = m_nHead;
//将记录指针移动到添加位置的前面
for(int i=0; i<idx; i++)
{
pre = pre->pNext;
}
//将当前节点的pNext赋值给temp的pNext
temp->pNext = pre->pNext;
//将temp的地址赋给 当前节点的pNext
pre->pNext = temp;
//长度自增
m_nLen++;
return true;
}
//删除一个节点
bool LListDel(_In_ int idx, _Out_ Type& data)
{
//判断参数
if (idx<0 || idx>=m_nLen)
{
return false;
}
//判断是否为空
if (LListIsEmpty())
{
return false;
}
//找到要删除的位置
//如果是头节点
if (idx == 0)
{
//将要删除的数据 赋值给传出数据
data = m_nHead->nData;
//创建一个临时节点
PNODE temp = new NODE;
temp = m_nHead;
temp = temp->pNext;
m_nHead = temp;
delete temp;
temp = nullptr;
//长度自减
m_nLen--;
return true;
}
//正常情况
//记录当前指针
PNODE temp = m_nHead;
//遍历到 要删除节点的前一个节点
for (int i = 0; i < idx-1; i++)
{
//当前节点的指针 移动到下一个节点
temp = temp->pNext;
}
//删除
//记录当前节点的pNext 此时temp为要删除的节点前一个节点
PNODE pre = nullptr;
pre = temp->pNext; //要删除节点的地址
//将数据传出
data = pre->nData;
temp->pNext = pre->pNext;
delete pre;
pre = nullptr;
m_nLen--;
return true;
}
//打印输出
void pri()
{
PNODE temp = m_nHead;
for (int i=0 ; i<m_nLen; i++)
{
std::cout << temp->nData <<std::endl;
temp = temp->pNext;
}
std::cout<<std::endl;
}
private:
PNODE m_nHead; //头指针
int m_nLen; //元素个数
};
int main()
{
CLinkList<int> cll;
cll.LListInsert(0, 11);
cll.LListInsert(0, 22);
cll.LListInsert(0, 33);
cll.pri();
system("pause");
return 0;
}