1. 简介
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
相比较于普通的线性表(数组),链表有自己的优势和劣势:
- 单个结点创建非常方便,普通的线性内存通常在创建的时候就需要设定数据的大小
- 结点的删除非常方便,不需要像线性结构那样移动剩下的数据
- 结点的访问方便,可以通过循环或者递归的方法访问到任意数据,但是平均的访问效率低于线性表
单向链表是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。
2. 链表的实现(C语言)
/*********************************************************************************
*Copyright(C),Your Company
*FileName: List.h
*Author: Huangjh
*Version:
*Date: 2018-01-02
*Description: 单向链表(C语言)实现
*Others:
**********************************************************************************/
#ifndef _LIST_H
#define _LIST_H
typedef int ElementType;
typedef struct __Node_t
{
ElementType Element;
struct __Node_t *pNext;
}Node;
Node *CreateNode(ElementType element);
void DeleteNode(Node *pNode);
void InitHead(Node *pHead);
int Empty(Node *pHead);
int IsLast(Node *pPosition);
Node *Find(ElementType element, Node *pHead);
Node *FindPrevious(ElementType element, Node *pHead);
void Delete(ElementType element, Node *pHead);
void Insert(ElementType element, Node *pHead, Node *pPosition);
void InsertHead(ElementType element, Node *pHead);
void InsertTail(ElementType element, Node *pHead);
void Reverse(Node *pHead);
#endif //#ifndef _LIST_H
/*********************************************************************************
*Copyright(C),Your Company
*FileName: List.cpp
*Author: Huangjh
*Version:
*Date: 2018-01-02
*Description: 带表头的单向链表(C语言)实现
*Others:
**********************************************************************************/
#include "stdlib.h"
#include "List.h"
//创建一个结点
Node *CreateNode(ElementType element)
{
Node *pNode = NULL;
pNode = (Node *)malloc(sizeof(Node));
if (pNode == NULL)
return NULL;
pNode->Element = element;
pNode->pNext = NULL;
return pNode;
}
//释放一个结点
void DeleteNode(Node *pNode)
{
if (pNode != NULL)
free(pNode);
}
void InitHead(Node *pHead)
{
pHead->Element = 0;
pHead->pNext = NULL;
}
//链表是否为空
int Empty(Node *pHead)
{
return pHead->pNext == NULL;
}
//是否是链表尾部
int IsLast(Node *pPosition)
{
return pPosition->pNext == NULL;
}
//查找成员element的位置
Node *Find(ElementType element, Node *pHead)
{
Node *pPosition = pHead->pNext;
while (pPosition != NULL && pPosition->Element != element)
pPosition = pPosition->pNext;
return pPosition;
}
//查找成员element的前驱
Node *FindPrevious(ElementType element, Node *pHead)
{
Node *pPosition = pHead;
while (pPosition->pNext != NULL && pPosition->pNext->Element != element)
pPosition = pPosition->pNext;
return pPosition;
}
//删除链表的某个结点
void Delete(ElementType element, Node *pHead)
{
Node *pPosition = FindPrevious(element, pHead);
if (!IsLast(pPosition))
{
Node *pCurrent = pPosition->pNext;
pPosition->pNext = pCurrent->pNext;
DeleteNode(pCurrent);
}
}
//在链表的某个位置插入
void Insert(ElementType element, Node *pHead, Node *pPosition)
{
Node *pNewNode = CreateNode(element);
if (pNewNode == NULL)
{
abort();
}
pNewNode->pNext = pPosition->pNext;
pPosition->pNext = pNewNode;
}
//在链表头部插入
void InsertHead(ElementType element, Node *pHead)
{
Node *pNewNode = CreateNode(element);
if (pNewNode == NULL)
{
abort();
}
if (!IsLast(pHead))
{
pNewNode->pNext = pHead->pNext;
}
pHead->pNext = pNewNode;
}
//在链表尾部插入
void InsertTail(ElementType element, Node *pHead)
{
Node *pNewNode = CreateNode(element);
if (pNewNode == NULL)
{
abort();
}
Node *pPosition = pHead;
while (!IsLast(pPosition))
pPosition = pPosition->pNext;
pPosition->pNext = pNewNode;
}
//单链表逆转,就是把链表中各节点next域改为指向其前驱结点,
//原先第一个结点的next域为空,head改为指向原先的最后一个
//结点
void Reverse(Node *pHead)
{
Node *pPre = NULL;
Node *pNext = NULL;
Node *pFirst = pHead->pNext;
while (pFirst)
{
pNext = pFirst->pNext;
pFirst->pNext = pPre;
pPre = pFirst;
pFirst = pNext;
}
pHead->pNext = pPre;
}
/*********************************************************************************
*Copyright(C),Your Company
*FileName: main.cpp
*Author: Huangjh
*Version:
*Date: 2018-01-02
*Description: 带表头的单向链表(C语言)实现的测试用例
*Others:
**********************************************************************************/
#include <stdio.h>
#include "List.h"
int main(void)
{
Node stHead; //表头,ElementType域未使用
Node *pNodeTemp = NULL;
Node *pNewHead = NULL;
//初始化表头
InitHead(&stHead);
//创建带有10个元素的链表
for (int i = 0; i < 10; i++)
{
InsertHead(i, &stHead);
}
printf("创建的链表:\r\n");
pNodeTemp = stHead.pNext;
while (pNodeTemp)
{
printf("%d ", pNodeTemp->Element);
pNodeTemp = pNodeTemp->pNext;
}
printf("\r\n");
Reverse(&stHead);
printf("逆序的链表:\r\n");
pNodeTemp = stHead.pNext;
while (pNodeTemp)
{
printf("%d ", pNodeTemp->Element);
pNodeTemp = pNodeTemp->pNext;
}
printf("\r\n");
//查找成员5
pNodeTemp = Find(5, &stHead);
printf("查找成员5:%d.\r\n", pNodeTemp->Element);
//删除成员5
Delete(5, &stHead);
printf("删除后的链表:\r\n");
pNodeTemp = stHead.pNext;
while (pNodeTemp)
{
printf("%d ", pNodeTemp->Element);
pNodeTemp = pNodeTemp->pNext;
}
return 0;
}
运行结果如下所示:
创建的链表:
9 8 7 6 5 4 3 2 1 0
逆序的链表:
0 1 2 3 4 5 6 7 8 9
查找成员5:5.
删除后的链表:
0 1 2 3 4 6 7 8 9
3. 链表的实现(C++)
后续有时间在重整c++版本。
/*********************************************************************************
*Copyright(C),Your Company
*FileName: List.h
*Author: Huangjh
*Version:
*Date: 2018-01-02
*Description: 单向链表(C++)实现
*Others:
**********************************************************************************/
#ifndef _LIST_H
#define _LIST_H
#include <iostream>
template<typename T>
class CSingleList
{
public:
CSingleList()
{
m_Head.pNext = NULL;
}
~CSingleList()
{
}
bool empty(void)
{
return m_Head.pNext == NULL;
}
//删除链表的某个结点
void Delete(T element)
{
Node *pPosition = FindPrevious(element);
if (!IsLast(pPosition))
{
Node *pCurrent = pPosition->pNext;
pPosition->pNext = pCurrent->pNext;
DeleteNode(pCurrent);
}
}
//在链表头部插入
void InsertHead(T element)
{
Node *pNewNode = CreateNode(element);
if (pNewNode == NULL)
{
abort();
}
if (!IsLast(&m_Head))
{
pNewNode->pNext = m_Head.pNext;
}
m_Head.pNext = pNewNode;
}
//在链表尾部插入
void InsertTail(T element)
{
Node *pNewNode = CreateNode(element);
if (pNewNode == NULL)
{
abort();
}
Node *pPosition = &m_Head;
while (!IsLast(pPosition))
pPosition = pPosition->pNext;
pPosition->pNext = pNewNode;
}
void Reverse()
{
Node *pPre = NULL;
Node *pNext = NULL;
Node *pFirst = m_Head.pNext;
while (pFirst)
{
pNext = pFirst->pNext;
pFirst->pNext = pPre;
pPre = pFirst;
pFirst = pNext;
}
m_Head.pNext = pPre;
}
//TODO:后续实现类似迭代器来访问,目前只为测试用
void printf(void)
{
Node *pNodeTemp = m_Head.pNext;
while (pNodeTemp)
{
std::cout << pNodeTemp->Element << " ";
pNodeTemp = pNodeTemp->pNext;
}
}
private:
typedef struct __Node_t
{
T Element;
struct __Node_t *pNext;
}Node;
Node *CreateNode(T Element)
{
Node *pNode = NULL;
pNode = new Node();
if (pNode == NULL)
return NULL;
pNode->Element = Element;
pNode->pNext = NULL;
return pNode;
}
void DeleteNode(Node *pNode)
{
if (pNode != NULL)
delete pNode;
}
bool IsLast(Node *pPosition)
{
return pPosition->pNext == NULL;
}
//查找成员element的位置
Node *Find(T element)
{
Node *pPosition = m_Head.pNext;
while (pPosition != NULL && pPosition->Element != element)
pPosition = pPosition->pNext;
return pPosition;
}
//查找成员element的前驱
Node *FindPrevious(T element)
{
Node *pPosition = &m_Head;
while (pPosition->pNext != NULL && pPosition->pNext->Element != element)
pPosition = pPosition->pNext;
return pPosition;
}
Node m_Head;
};
#endif //#ifndef _LIST_H
/*********************************************************************************
*Copyright(C),Your Company
*FileName: main.cpp
*Author: Huangjh
*Version:
*Date: 2018-01-02
*Description: 带表头的单向链表(C++)实现的测试用例
*Others:
**********************************************************************************/
#include <iostream>
#include "List.h"
#include <iostream>
using namespace std;
int main(void)
{
CSingleList<int> cSingleList;
for (int i = 0; i < 10; i++)
{
cSingleList.InsertHead(i);
}
cout << "创建的链表:" << endl;
cSingleList.printf();
cout << endl;
cout << "逆序的链表:" << endl;
cSingleList.Reverse();
cSingleList.printf();
cout << endl;
//删除成员为5的结点
cout << "删除后的链表:" << endl;
cSingleList.Delete(5);
cSingleList.printf();
cout << endl;
return 0;
}
运行结果:
创建的链表:
9 8 7 6 5 4 3 2 1 0
逆序的链表:
0 1 2 3 4 5 6 7 8 9
删除后的链表:
0 1 2 3 4 6 7 8 9