1.关于链表
链表的特点:
1】数据分散存储
2】查询性能没有Vector好
3】新增与删除的性能好于Vector
链表的种类:
单链表 ->由多个节点组成,每一个节点中保存数据和下一个节点的指针;
循环链表 ->最后一个节点中的指针指向头结点;
双向链表 ->每个节点多维护一个指针,两个指针分别指向前一个节点和后一个节点,可以从正反两个方向来查找元素;
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(); }
结果: