数据结构——单向链表

1. 简介

  链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
相比较于普通的线性表(数组),链表有自己的优势和劣势:
  1. 单个结点创建非常方便,普通的线性内存通常在创建的时候就需要设定数据的大小
  2. 结点的删除非常方便,不需要像线性结构那样移动剩下的数据
  3. 结点的访问方便,可以通过循环或者递归的方法访问到任意数据,但是平均的访问效率低于线性表
  单向链表是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。

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


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值