1.关于链表
.png)
链表的特点:
1】数据分散存储
2】查询性能没有Vector好
3】新增与删除的性能好于Vector
链表的种类:
单链表 ->由多个节点组成,每一个节点中保存数据和下一个节点的指针;
循环链表 ->最后一个节点中的指针指向头结点;
双向链表 ->每个节点多维护一个指针,两个指针分别指向前一个节点和后一个节点,可以从正反两个方向来查找元素;
.png)
2.实现单链表
头文件:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#define INDEX_IS_ERROR -2 // 错误的索引号
#define BUFFER_IS_EMPTY -3 // 缓冲区已空
#include "stdio.h"
#include "windows.h"
#include "stdlib.h"
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){
return TRUE;
}
return FALSE;
}
//清空链表
template<class T_ELE> void LinkedList<T_ELE>::Clear()
{
// 1. 判断链表是否为空
if(IsEmpty()){
return;
}
// 2. 循环删除链表中的节点
while(!m_pList){
PNODE temp = m_pList;
m_pList = m_pList->pNext;
delete temp;
}
// 3. 删除最后一个节点并将链表长度置为0
m_pList = NULL;
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-1)){
return INDEX_IS_ERROR;
}
// 2. 取得索引指向的节点
PNODE pElem = m_pList;
for(int i=0;i<dwIndex;i++){
pElem = pElem->pNext;
}
// 3. 将索引指向节点的值复制到OUT参数
memcpy(&Element, pElem, sizeof(T_ELE));
}
//根据元素内容获取索引
template<class T_ELE> DWORD LinkedList<T_ELE>::GetElementIndex(IN T_ELE& Element)
{
// 1. 判断链表是否为空
if(IsEmpty()){
return -1;
}
// 2. 循环遍历链表,找到与Element相同的元素
PNODE temp = m_pList;
int i=0;
while(temp){
if(temp->Data == Element){
return i;
}
temp = temp->pNext;
i++;
}
return -1;
}
//在链表尾部新增节点
template<class T_ELE> DWORD LinkedList<T_ELE>::Insert(IN T_ELE Element)
{
PNODE newNode = new NODE;
memcpy(newNode, &Element, sizeof(T_ELE));
newNode->pNext = NULL;
//1.判断链表是否为空
if(IsEmpty()){
m_pList = newNode;
m_dwLength++;
return 1;
}
//2.如果链表不为空
PNODE temp = m_pList;
while(temp->pNext){
temp = temp->pNext;
}
temp ->pNext = newNode;
m_dwLength++;
return 1;
}
//将节点新增到指定索引的位置
template<class T_ELE> DWORD LinkedList<T_ELE>::Insert(IN DWORD dwIndex, IN T_ELE Element)
{
// 1. 判断链表是否为空
if(IsEmpty() && dwIndex!=0){
return -1;
}
// 2. 判断索引值是否有效
if(dwIndex<0 || dwIndex>m_dwLength){
return INDEX_IS_ERROR;
}
PNODE newNode = new NODE;
memcpy(newNode, &Element, sizeof(T_ELE));
// 3. 如果索引为0
if(dwIndex == 0){
newNode->pNext = m_pList;
m_pList = newNode;
}
// 4. 如果索引为链表尾
else if(dwIndex == m_dwLength){
PNODE temp = m_pList;
while(temp->pNext){
temp=temp->pNext;
}
temp->pNext = newNode;
newNode->pNext = NULL;
}
// 5. 如果索引为链表中
else{
PNODE temp = m_pList;
for(int i=0;i<dwIndex-1;i++){
temp = temp->pNext;
}
newNode->pNext = temp->pNext;
temp->pNext = newNode;
}
m_dwLength++;
return 1;
}
//根据索引删除节点
template<class T_ELE> DWORD LinkedList<T_ELE>::Delete(IN DWORD dwIndex)
{
// 1. 判断链表是否为空
if(IsEmpty()){
return -1;
}
// 2. 判断索引值是否有效
if(dwIndex<0 || dwIndex>=m_dwLength){
return INDEX_IS_ERROR;
}
if(dwIndex == 0){
if(m_pList->pNext == NULL){
// 3. 如果链表中只有头节点,且要删除头节点
delete m_pList;
m_pList = NULL;
}else{
// 4. 如果要删除头节点
PNODE temp = m_pList;
m_pList = m_pList->pNext;
delete temp;
}
}else{
// 5. 如果是其他情况
PNODE temp = m_pList;
for(int i=0;i<dwIndex-1;i++){
temp = temp->pNext;
}
PNODE index = temp->pNext;
temp->pNext = index->pNext;
delete index;
}
m_dwLength--;
return 1;
}
//获取链表中节点的数量
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)
{
// 就是一个循环
}
//获取dwIndex节点的地址
template<class T_ELE>
LinkedList<T_ELE>::PNODE LinkedList<T_ELE>::GetIndexCurrentNode(DWORD dwIndex)
{
// 就是一个循环
}
//获取dwIndex后面节点的地址
template<class T_ELE>
LinkedList<T_ELE>::PNODE LinkedList<T_ELE>::GetIndexNextNode(DWORD dwIndex)
{
// 就是一个循环
}
#endif
测试:
#include "MyLinkedList.h"
template <class T_ELE>
void printList(LinkedList<T_ELE>* list){
for(int i=0;i<list->GetSize();i++){
T_ELE k;
list->GetElement(i,k);
printf("%d\t",k);
}
printf("\n");
}
void fun(){
LinkedList<int>* list = new LinkedList<int>();
//结尾插入
list->Insert(1);
list->Insert(2);
list->Insert(3);
printList(list);
//获取索引
int a = 2;
int index = list->GetElementIndex(a);
printf("2的索引是:%d\n", index);
//索引插入
int c=0,d=4;
list->Insert(0, c);
list->Insert(4, d);
printList(list);
//删除
list->Delete(0);
list->Delete(2);
list->Delete(2);
printList(list);
}
void main(){
fun();
getchar();
}
结果:
.png)