1.链表的特点
特点:
1.数据分散存储
2.查询性能没有Vector好
3.新增与删除性能好于Vector
2.链表的种类
3.链表的实现
#include<stdio.h>
#include<Windows.h>
#define SUCCESS 1 // 执行成功
#define ERROR -1 // 执行失败
#define INDEX_IS_ERROR -2 // 错误的索引号
#define BUFFER_IS_EMPTY -3 // 缓冲区已空
template <class T_ELE>
class LinkedList
{
public:
LinkedList();
~LinkedList();
public:
BOOL IsEmpty(); //判断链表是否为空 空返回1 非空返回0
void 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;
PNODE GetIndexCurrentNode(DWORD dwIndex); //获取索引为dwIndex的指针
PNODE GetIndexPreviousNode(DWORD dwIndex); //获取索引为dwIndex的前一个节点指针
PNODE GetIndexNextNode(DWORD dwIndex); //获取索引为dwIndex的后一个节点指针
private:
PNODE m_pList; //链表头指针,指向第一个节点
DWORD m_dwLength; //元素的数量
};
//无参构造函数 初始化成员
template<class T_ELE> LinkedList<T_ELE>::LinkedList()
:m_pList(NULL),m_dwLength(0)
{
}
//析构函数 清空元素
template<class T_ELE> LinkedList<T_ELE>::~LinkedList()
{
Clear();
}
//判断链表是否为空
template<class T_ELE> BOOL LinkedList<T_ELE>::IsEmpty()
{
if(m_pList==NULL || m_dwLength==0)
return true;
else
return false;
}
//清空链表
template<class T_ELE> void LinkedList<T_ELE>::Clear()
{
// 1. 判断链表是否为空
if(m_pList!=NULL)
{
// 2. 循环删除链表中的节点
PNODE tmpListp=m_pList;
for(int i=0;i<m_dwLength;i++)
{
delete tmpListp;
tmpListp=tmpListp->pNext;
}
// 3. 删除最后一个节点并将链表长度置为0
m_dwLength=0;
}
}
//根据索引获取元素
template<class T_ELE> DWORD LinkedList<T_ELE>::GetElement(IN DWORD dwIndex,OUT T_ELE& Element)
{
// 1. 判断索引是否有效
if(dwIndex<0 || dwIndex>=m_dwLength)
{
return INDEX_IS_ERROR;
}
// 2. 取得索引指向的节点
PNODE tmpListp=m_pList;
for(int i=0;i<dwIndex;i++)
tmpListp=tmpListp->pNext;
// 3. 将索引指向节点的值复制到OUT参数
Element=tmpListp->Data;
return Element;
}
//根据元素内容获取索引
template<class T_ELE> DWORD LinkedList<T_ELE>::GetElementIndex(IN T_ELE Element)
{
// 1. 判断链表是否为空
if(m_pList==NULL || m_dwLength==0)
return BUFFER_IS_EMPTY;
// 2. 循环遍历链表,找到与Element相同的元素
PNODE tmpListp=m_pList;
for(int i=0;i<m_dwLength;i++)
{
if(memcmp(&tmpListp->Data,&Element,sizeof(T_ELE))==0)
return i;
tmpListp=tmpListp->pNext;
}
return ERROR;
}
//在链表尾部新增节点
template<class T_ELE> DWORD LinkedList<T_ELE>::Insert(IN T_ELE Element)
{
PNODE newNodep=new NODE;
memset(newNodep,0,sizeof(NODE));
memcpy(&newNodep->Data,&Element,sizeof(T_ELE));
// 1. 判断链表是否为空
if(m_pList==NULL || m_dwLength==0)
{
m_pList=newNodep;//修改指针
m_dwLength++;//修改长度
return SUCCESS;
}
// 2. 如果链表中已经有元素
PNODE tmpNodep=m_pList;
for(int i=0;i<m_dwLength-1;i++)
tmpNodep=tmpNodep->pNext;
tmpNodep->pNext=newNodep;
m_dwLength++;
return SUCCESS;
}
//将节点新增到指定索引的位置 0 1 2 3 4
template<class T_ELE> DWORD LinkedList<T_ELE>::Insert(IN DWORD dwIndex, IN T_ELE Element)
{
PNODE newNodep=new NODE;
memset(newNodep,0,sizeof(NODE));
memcpy(&newNodep->Data,&Element,sizeof(T_ELE));
// 1. 判断链表是否为空
if(m_pList==NULL || m_dwLength==0)
{
if(dwIndex==0) //在链表为空的情况下,索引不为0就是索引错误
{
m_pList=newNodep;//修改指针
m_dwLength++;//修改长度
return SUCCESS;
}
else
return INDEX_IS_ERROR;
}
// 2. 判断索引值是否有效
if(dwIndex<0 || dwIndex>=m_dwLength)
return INDEX_IS_ERROR;
// 3. 如果索引为0
if(deIndex==0)
{
PNODE tmpListp=m_pList;
tmpListp=tmpListp->pNext;//获得第二节点地址
m_pList=newNodep;
m_pList->pNext=tmpListp;
m_dwLength++;
}
// 4. 如果索引为链表尾
else if(dwIndex==(m_dwLength-1))
{
PNODE tmpListp=m_pList;
while(tmpListp->pNext==0)
tmpListp=tmpListp->pNext;//获得最后一节点的地址
tmpListp->pNext=newNodep;
m_dwLength++;
}
// 5. 如果索引为链表中
else
{
PNODE tmpListp=m_pList,tmpListp1;
for(int i=0;i<dwIndex;i++)
tmpListp=tmpListp->pNext;// 获得索引节点的地址
for(int i=0;i<=dwIndex;i++)
tmpListp1=tmpListp1->pNext;
tmpListp->pNext=newNodep;
newNodep->pNext=tmpListp;
m_dwLength++;
}
}
//根据索引删除节点
template<class T_ELE> DWORD LinkedList<T_ELE>::Delete(IN DWORD dwIndex)
{
// 1. 判断链表是否为空
if(m_pList==0 || m_dwLength==0)
return BUFFER_IS_EMPTY;
// 2. 判断索引值是否有效
if(dwIndex<0 || dwIndex>=m_dwLength)
return INDEX_IS_ERROR;
// 3. 如果链表中只有头节点,且要删除头节点
if(m_dwLength==0)
{
if(dwIndex==0)
{
delete m_pList;
m_pList==NULL;
m_dwLength--;
return SUCCESS;
}
else
printf("元素不足\n");
}
// 4. 如果要删除头节点
else if(dwIndex==0)
{
m_pList=m_pList->pNext;
delete m_pList;
m_pList==NULL;
m_dwLength--;
}
// 5. 如果是其他情况
else if(dwIndex==m_dwLength-1)
{
PNODE p1=GetIndexPreviousNode(dwIndex);//得到索引前一位地址
PNODE p2=GetIndexCurrentNode(dwIndex);//得到索引位置的地址
p1->pNext=0;
delete p2;
m_dwLength--;
}
else
{
PNODE p1=GetIndexPreviousNode(dwIndex);//得到索引前一位地址
PNODE p2=GetIndexCurrentNode(dwIndex);//得到索引位置的地址
//PNODE p3=GetIndexNextNode(dwIndex);//得到索引后一位的地址
p1->pNext=p2->pNext;
delete p2;
m_dwLength--;
return SUCCESS;
}
}
//获取链表中节点的数量
template<class T_ELE> DWORD LinkedList<T_ELE>::GetSize()
{
return m_dwLength;
}
//获取dwIndex前面节点的地址
template<class T_ELE>
LinkedList<T_ELE>::PNODE LinkedList<T_ELE>::GetIndexPreviousNode(DWORD dwIndex)
{
// 就是一个循环
PNODE tmpListp=m_pList;
for(int i=0;i<dwIndex-1;i++)
tmpListp=tmpListp->pNext;
return tmpListp;
}
//获取dwIndex节点的地址
template<class T_ELE>
LinkedList<T_ELE>::PNODE LinkedList<T_ELE>::GetIndexCurrentNode(DWORD dwIndex)
{
// 就是一个循环
PNODE tmpListp=m_pList;
for(int i=0;i<dwIndex;i++)
tmpListp=tmpListp->pNext;
return tmpListp;
}
//获取dwIndex后面节点的地址
template<class T_ELE>
LinkedList<T_ELE>::PNODE LinkedList<T_ELE>::GetIndexNextNode(DWORD dwIndex)
{
// 就是一个循环
PNODE tmpListp=m_pList;
for(int i=0;i<dwIndex+1;i++)
tmpListp=tmpListp->pNext;
return tmpListp;
}
void Test()
{
LinkedList<int>* lin=new LinkedList<int>;
lin->Insert(1);
lin->Insert(2);
lin->Insert(3);
lin->Insert(4);
//lin->Clear();
//int x=lin->GetElement(2,x);
//printf("%d\n",x);
//lin->Delete(3);
int i=lin->GetElementIndex(4);
printf("索引是:%d\n",i);
}
int main()
{
Test();
return 0;
}