动态单链表的实现

最近本人开始为找工作做准备,于是想把几种常用的数据结构用自己的代码实现出来,在实现的过程中,发现问题多多,现将本人实现的过程中所犯的错误(相信也有不少和我一样的菜鸟犯过同样的错误),以及为什么会出现错误,如何解决该错误的过程记录于此,方便它人的同时,也方便自己日后查阅。
/******************************************************************************************************
* Description:	动态单向链表的实现
* Author:		Sky
* Time:			2014.04.14
* Language:		C/C++
* Note:			1、单向链表是由表头唯一确定的,因此单向链表可以用头指针/结点的名字来命名。 
				2、空链表表示只含有头结点的链表。注意区分链表销毁和链表清空操作。
******************************************************************************************************/
#include "stdafx.h"
#include <iostream>
using namespace std;
typedef int Elemtype;
struct ListNode
{
	Elemtype Elem; // 数据域(不一定为int型,可以为任何用户自定义的类型、包括结构体、类、数组等)
	ListNode* pNext; // 指针域(指向下一个结点)
};

bool ListInit(ListNode* L); // 单向链表初始化(构造一个空的单向链表,即仅含头结点的单向链表)void ListDestory(ListNode* L); // 单向链表的销毁
void ListClear(ListNode* L); // 单向链表的清空
bool ListInsert(ListNode* L, const int& i, const Elemtype& Elem); // 向链表中指定位置i之前插入一个元素
bool ListDelete(ListNode* L, const int& i, Elemtype& Elem); // 删除链表中指定位置i的一个元素,并返回删除元素
int ListFind(ListNode* L, const Elemtype& CurElem, bool (*compare)(const Elemtype&, const Elemtype&));// 返回链表中第一个满足关系compare()的数据元素的位序。
bool PriorElem(ListNode* L, const Elemtype& CurElem, Elemtype& PreElem); // 返回当前元素的前一元素
bool NextElem(ListNode* L, const Elemtype& CurElem, Elemtype& NextElem); // 返回当前元素的后一元素
bool GetElem(ListNode* L, const int& i, Elemtype& Elem); // 获取当前位序处的元素值
bool ListEmpty(ListNode* L); // 判断单向链表是否为空
int ListLength(ListNode* L); // 返回链表长度
void ListTravesal(ListNode* L); // 链表遍历

int _tmain(int argc, _TCHAR* argv[])
{
	int a[] = {1,5,9,8,6,14,25,39,68,59,65,26,77,69};
	ListNode* L = NULL;ListInit(L);
	for(int i=0; i<7; i++)
		ListInsert(L, i+1, a[i]);
	ListTravesal(L);
	while(true);
	return 0;
}

/**************************************************************************************
* Author:		Sky
* Functiuon:	ListInit() 
* Description: 动态单向链表的初始化,构造一个空的单向链表 
* Access Level:NULL
* Input: 
* Output:		L: 待初始化的单向链表头结点 
* Return:		false/true 
**************************************************************************************/
bool ListInit(ListNode* L) // 如果形参为ListNode* ,当传入一个ListNode的指针时,实际传入的是指针的拷贝,函数内部任何对L的操作与传入的实参无关
{
	L = new ListNode;
	if(NULL == L)
		return false;
	L->pNext = NULL;
	return true;
}
/**************************************************************************************
* Author:		Sky
* Functiuon:	ListDestory() 
* Description: 单向链表的销毁 
* Access Level: NULL
* Input:		L:待销毁的链表的头结点 
* Output:		NULL 
* Return:		NULL 
**************************************************************************************/
void ListDestory(ListNode* L)
{
	ListNode* pNextNode = NULL;
	while(NULL != L)
	{
		pNextNode = L->pNext;
		delete L;
		L = pNextNode;
	}
}
/**************************************************************************************
* Author:		Sky
* Functiuon:	ListClear() 
* Description: 清空单向链表,即:将已有单向链表变为一个空链表 
* Access Level: NULL
* Input:		L: 待清空单向链表的头结点 
* Output:		NULL 
* Return:		NULL 
**************************************************************************************/
void ListClear(ListNode* L)
{
	ListNode* pNextNode = NULL;
	L = L->pNext;
	while(NULL != L)
	{
		pNextNode = L->pNext;
		delete L;
		L = pNextNode;
	}
}
/**************************************************************************************
* Author:		Sky
* Functiuon:	ListInsert() 
* Description: 向单向链表中指定位序处插入一个元素 
* Access Level:NULL
* Input:		L: 被插入的单向链表头结点
				i: 待插入元素在链表中的位序
				Elem: 待插入元素
* Output:		NULL
* Return:		false/true 
**************************************************************************************/
bool ListInsert(ListNode* L, const int& i, const Elemtype& Elem)
{
	bool bResult = false;
	ListNode* pCurNode = L;
	ListNode* pNewNode = NULL;
	int j = 0;
	if(i>=1 && i<=ListLength(L)+1)
	{
		for(j=0; j<i-1; j++)
		{
			pCurNode = pCurNode->pNext;
		}
		bResult = true;
		pNewNode = new ListNode;
		pNewNode->Elem = Elem;
		pNewNode->pNext = pCurNode->pNext;
		pCurNode->pNext = pNewNode;
	}
	return bResult;
}
/**************************************************************************************
 * Author:			Sky
 * Functiuon:		ListDelete() 
 * Description:	删除链表中指定位序处的结点,并返回删除结点的值 
 * Access Level:	NULL
 * Input:			L: 待删除结点所在链表
					i: 待删除结点在链表中的位序(1~Length(L))
 * Output:			Elem: 被删除的元素 
 * Return:			false/true
 **************************************************************************************/
bool ListDelete(ListNode* L, const int& i, Elemtype& Elem)
{
	bool bResult = false;
	ListNode* pCurNode = L;
	ListNode* pNextNode = NULL;
	int j = 0;
	if(i>=1 && i<=ListLength(L))
	{
		for(j=0; j<i-1; j++)
		{
			pCurNode = pCurNode->pNext;
		}
		bResult = true;
		pNextNode = pCurNode->pNext->pNext;
		Elem = pCurNode->pNext->Elem;
		delete pCurNode->pNext;
		pCurNode->pNext = pNextNode;
	}
	return bResult;
}
/**************************************************************************************
* Author:			Sky
* Functiuon:		ListFind() 
* Description:		找出链表中与指定元素CurElem满足条件compare()的元素,返回其在链表中的位序 
* Access Level:	NULL
* Input:			L: 待检索链表
					CurElem: 检索元素
					compare: 函数指针,检索条件
* Output:			NULL 
* Return:			-1: 查找失败
					其它: 返回找到的元素在链表中的位序号。
**************************************************************************************/
int ListFind(ListNode* L, const Elemtype& CurElem, bool (*compare)(const Elemtype&, const Elemtype&))
{
	ListNode* pCurNode = L;
	int i = 0;
	while(NULL != pCurNode)
	{
		if(compare(CurElem, pCurNode->Elem))
		{
			return i;
		}
		else
		{
			pCurNode = pCurNode->pNext;
			i++;
		}
	}
	return -1;
}
/**************************************************************************************
* Author:			Sky
* Functiuon:		PriorElem() 
* Description:		返回单向链表中指定元素的前一个元素 
* Access Level:	NULL
* Input:			L: 单向链表 
					CurElem:指定元素
* Output:			PreElem:单向链表中指定元素的前一个元素 
* Return:			false/true 
**************************************************************************************/
bool PriorElem(ListNode* L, const Elemtype& CurElem, Elemtype& PreElem)
{
	bool bResult = false;
	ListNode* pCurNode = NULL;
	ListNode* pPreNode = NULL;
	pCurNode = L->pNext->pNext; // pCurNode初始指向第二个结点
	pPreNode = L->pNext; // pPreNode初始指向第一个结点
	while(NULL != pCurNode) // 当前结点存在
	{
		if(CurElem == pCurNode->Elem)
		{
			PreElem = pPreNode->Elem;
			bResult = true;
			break;
		}
		else
		{
			pCurNode = pCurNode->pNext;
			pPreNode = pPreNode->pNext;
		}
	}
	return bResult;
}
/**************************************************************************************
* Author:		Sky
* Functiuon:	NextElem() 
* Description: 返回单向链表中指定元素的后一个元素 
* Access Level: NULL
* Input:		L: 单向链表
				CurElem: 指定元素
* Output:		NextElem:单向链表中指定元素的后一个元素 
* Return:		false/true
**************************************************************************************/
bool NextElem(ListNode* L, const Elemtype& CurElem, Elemtype& NextElem)
{
	bool bResult = false;
	ListNode* pCurNode = NULL;
	ListNode* pNextNode = NULL;
	pCurNode = L->pNext;pNextNode = L->pNext->pNext;
	while(NULL != pNextNode)
	{
		if(CurElem == pCurNode->Elem)
		{
			NextElem = pNextNode->Elem;
			bResult = true;
			break;
		}
		else
		{
			pCurNode = pCurNode->pNext;
			pNextNode = pNextNode->pNext;
		}
	}
	return bResult;
}
/**************************************************************************************
 * Author:			Sky
 * Functiuon:		GetElem() 
 * Description:	返回单向链表中指定位序处的元素 
 * Access Level:	NULL
 * Input:			L: 单向链表
					i: 待获取的元素在单向链表中的位序
 * Output:			Elem:单向链表中指定位序处的元素 
 * Return:			fasle/true
 **************************************************************************************/
bool GetElem(ListNode* L, const int& i, Elemtype& Elem)
{
	bool bResult = false;
	ListNode* pCurNode = NULL;
	int j = 0;
	pCurNode = L;
	if(i>=1 && i<=ListLength(L))
	{
		for(j=0; j<i; j++)
		{
			pCurNode = pCurNode->pNext;
		}
		Elem = pCurNode->Elem;
		bResult = true;
	}
	return bResult;
}
/**************************************************************************************
* Author:		Sky
* Functiuon:	ListEmpty() 
* Description: 判断单向链表是否为空链表 
* Access Level: NULL
* Input:		L: 待判断单向链表头结点 
* Output:		NULL
* Return:		false: 该单向链表不是空链表
				true: 该单向链表是空链表
**************************************************************************************/
bool ListEmpty(ListNode* L)
{
	bool bResult = false;
	ListNode* pCurNode = L;
	if(NULL == pCurNode->pNext)
		bResult = true;
	return bResult;
}
/**************************************************************************************
* Author:		Sky
* Functiuon:	ListLength() 
* Description: 返回指定单向链表的长度
* Access Level: NULL
* Input:		L: 单向链表头结点
* Output:		NULL 
* Return:		单向链表长度 
**************************************************************************************/
int ListLength(ListNode* L)
{
	ListNode* pCurNode = L->pNext;
	int Len = 0;
	while(NULL != pCurNode)
	{
		Len++;
		pCurNode = pCurNode->pNext;
	}
	return Len;
}
/**************************************************************************************
* Author:		Sky
* Functiuon:	ListTravesal() 
* Description: 从头结点到尾节点遍历一个单向链表
* Access Level: NULL
* Input:		L: 待遍历单向链表 
* Output:		NULL 
* Return:		NULL 
**************************************************************************************/
void ListTravesal(ListNode* L)
{
	ListNode* pCurNode = L->pNext;
	while(NULL != pCurNode)
	{	
		cout<<pCurNode->Elem<<endl;	
		pCurNode = pCurNode->pNext;
	}
}
运行程序后程序出现错误,调试单步跟踪发现是内存访问越界,L未被初始化,而主函数中我调用了ListInit(L),为什么没有初始化呢?原来在ListInit()函数中采用的非引用形参ListNode* ,当将指针L作为实参实际传递的是L的一个拷贝,该函数内部任何执行动作与L无关。因此我们应当传递指针的引用或者传递指针的指针。修改后的代码如下:


/******************************************************************************************************
*	Description: 动态单向链表的实现
*	Author:      Sky
*	Time:	     2014.04.14
*   Language:    C/C++
*	Note:        1、单向链表是由表头唯一确定的,因此单向链表可以用头指针/结点的名字来命名。
				 2、空链表表示只含有头结点的链表。注意区分链表销毁和链表清空操作。
				 3、对单链表的操作,为什么传入参数均为指向头结点指针的指针或头结点指针的引用,而不是头结点指针?
******************************************************************************************************/
#include "stdafx.h"
#include <iostream>
using namespace std;

typedef int Elemtype;

struct ListNode
{
	Elemtype Elem;			//	数据域(不一定为int型,可以为任何用户自定义的类型、包括结构体、类、数组等)
	ListNode *pNext;		//	指针域(指向下一个结点)
};

bool ListInit(ListNode *&L);			//	单向链表初始化(构造一个空的单向链表,即仅含头结点的单向链表)
void ListDestory(ListNode *&L);			//	单向链表的销毁
void ListClear(ListNode *&L);			//	单向链表的清空
bool ListInsert(ListNode *&L, const int &i, const Elemtype &Elem);	//	向链表中指定位置i之前插入一个元素
bool ListDelete(ListNode *&L, const int &i, Elemtype &Elem);			//	删除链表中指定位置i的一个元素,并返回删除元素
int  ListFind(ListNode *&L, const Elemtype &CurElem, bool (*compare)(const Elemtype &, const Elemtype &));// 返回链表中第一个满足关系compare()的数据元素的位序。
bool PriorElem(ListNode *&L, const Elemtype &CurElem, Elemtype &PreElem);				   // 返回当前元素的前一元素
bool NextElem(ListNode *&L, const Elemtype &CurElem, Elemtype &NextElem);				   // 返回当前元素的后一元素
bool GetElem(ListNode *&L, const int &i, Elemtype &Elem);								   // 获取当前位序处的元素值
bool ListEmpty(ListNode *&L);															   // 判断单向链表是否为空
int  ListLength(ListNode *&L);															   // 返回链表长度
void ListTravesal(ListNode *&L);															   // 链表遍历


int _tmain(int argc, _TCHAR* argv[])
{
	int a[] = {1,5,9,8,6,14,25,39,68,59,65,26,77,69};
	ListNode *L = NULL;
	Elemtype e, Pre_e, Next_e;

	ListInit(L);
	for(int i=0; i<7; i++)
		ListInsert(L, i+1, a[i]);
	ListTravesal(L);
	GetElem(L, 4, e);
	cout<<"The 4th Elem is: "<<e<<endl;
	cout<<"ListLength(L) = "<<ListLength(L)<<endl;

	PriorElem(L, 9, Pre_e);
	NextElem(L, 9, Next_e);
	cout<<"Pre_e = "<<Pre_e<<endl;
	cout<<"Next_e = "<<Next_e<<endl;

	ListDelete(L, 3, e);
	ListTravesal(L);
	cout<<"ListLength(L) = "<<ListLength(L)<<endl;


	while(true);
	return 0;
}
/**************************************************************************************
* Author:				Sky	
* Functiuon:			ListInit()          
* Description:			动态单向链表的初始化,构造一个空的单向链表         
* Access Level:		NULL
* Input:   
* Output:				L: 待初始化的单向链表头结点 			       
* Return:				false/true       
**************************************************************************************/
bool ListInit(ListNode *&L)	//	如果形参为ListNode* ,即非引用形参,实际传入的是指针的拷贝,函数内部任何对
							//	指针L的操作与传入的实参无关,因此此处需传入双重指针,或指针的引用
{							//	
	L = new ListNode;
	if(NULL == L)
		return false;
	L->pNext = NULL;
	return true;
}
/**************************************************************************************
* Author:				Sky
* Functiuon:			ListDestory()          
* Description:			单向链表的销毁        
* Access Level:		NULL
* Input:				L:待销毁的链表的头结点             
* Output:				NULL         
* Return:				NULL        
**************************************************************************************/
void ListDestory(ListNode *&L)
{
	ListNode *pNextNode = NULL;
	while(NULL != L)
	{
		pNextNode = L->pNext;
		delete L;
		L = pNextNode;
	}
}
/**************************************************************************************
* Author:				Sky	
* Functiuon:			ListClear()           
* Description:			清空单向链表,即:将已有单向链表变为一个空链表        
* Access Level:		NULL
* Input:				L: 待清空单向链表的头结点   
* Output:				NULL      
* Return:				NULL       
**************************************************************************************/
void ListClear(ListNode *&L)
{
	ListNode *pNextNode = NULL;
	L = L->pNext;
	while(NULL != L)
	{
		pNextNode = L->pNext;
		delete L;
		L = pNextNode;
	}
}
/**************************************************************************************
* Author:				Sky
* Functiuon:			ListInsert()          
* Description:			向单向链表中指定位序处插入一个元素        
* Access Level:		NULL
* Input:				L:		被插入的单向链表头结点
						i:		待插入元素在链表中的位序
						Elem:	待插入元素
* Output:				NULL		
* Return:				false/true        
**************************************************************************************/
bool ListInsert(ListNode *&L, const int &i, const Elemtype &Elem)
{
	bool bResult = false;
	ListNode *pCurNode = L;
	ListNode *pNewNode = NULL;
	int j = 0;

	if(i>=1 && i<=ListLength(L)+1)
	{
		for(j=0; j<i-1; j++)
		{
			pCurNode = pCurNode->pNext;
		}
		bResult = true;
		pNewNode = new ListNode;
		pNewNode->Elem = Elem;
		pNewNode->pNext = pCurNode->pNext;
		pCurNode->pNext = pNewNode;
	}
	return bResult;
}
/**************************************************************************************
* Author:				Sky	
* Functiuon:			ListDelete()           
* Description:			删除链表中指定位序处的结点,并返回删除结点的值         
* Access Level:		NULL
* Input:				L:    待删除结点所在链表
						i:    待删除结点在链表中的位序(1~Length(L))
* Output:				Elem: 被删除的元素			         
* Return:				false/true
**************************************************************************************/
bool ListDelete(ListNode *&L, const int &i, Elemtype &Elem)
{
	bool bResult = false;
	ListNode *pCurNode = L;
	ListNode *pNextNode = NULL;
	int j = 0;

	if(i>=1 && i<=ListLength(L))
	{
		for(j=0; j<i-1; j++)
		{
			pCurNode = pCurNode->pNext;
		}
		bResult = true;
		pNextNode = pCurNode->pNext->pNext;
		Elem = pCurNode->pNext->Elem;
		delete pCurNode->pNext;
		pCurNode->pNext = pNextNode;
	}
	return bResult;
}
/**************************************************************************************
* Author:				Sky
* Functiuon:			ListFind()          
* Description:			找出链表中与指定元素CurElem满足条件compare()的元素,返回其在链表中的位序        
* Access Level:		NULL
* Input:				L:			待检索链表
						CurElem:	检索元素
						compare:    函数指针,检索条件
* Output:				NULL         
* Return:				-1:		查找失败
						其它:		返回找到的元素在链表中的位序号。
**************************************************************************************/
int ListFind(ListNode *&L, const Elemtype &CurElem, bool (*compare)(const Elemtype &, const Elemtype &))
{
	ListNode *pCurNode = L;
	int i = 0;

	while(NULL != pCurNode)
	{
		if(compare(CurElem, pCurNode->Elem))
		{
			return i;
		}
		else
		{
			pCurNode = pCurNode->pNext;
			i++;
		}
	}
	return -1;
}
/**************************************************************************************
* Author:				Sky	
* Functiuon:			PriorElem()           
* Description:			返回单向链表中指定元素的前一个元素         
* Access Level:		NULL
* Input:				L:       单向链表  
						CurElem: 指定元素
* Output:				PreElem:单向链表中指定元素的前一个元素       
* Return:				false/true        
**************************************************************************************/
bool PriorElem(ListNode *&L, const Elemtype &CurElem, Elemtype &PreElem)
{
	bool bResult = false;
	ListNode *pCurNode = NULL;
	ListNode *pPreNode = NULL;

	if(2 <= ListLength(L))
	{
		pCurNode = L->pNext->pNext;							// pCurNode初始指向第二个结点
		pPreNode = L->pNext;								// pPreNode初始指向第一个结点
		while(NULL != pCurNode)								// 当前结点存在
		{
			if(CurElem == pCurNode->Elem)
			{
				PreElem = pPreNode->Elem;
				bResult = true;
				break;
			}
			else
			{
				pCurNode = pCurNode->pNext;
				pPreNode = pPreNode->pNext;
			}
		}
	}
	return bResult;
}
/**************************************************************************************
* Author:				Sky
* Functiuon:			NextElem()          
* Description:			返回单向链表中指定元素的后一个元素        
* Access Level:		NULL
* Input:				L:       单向链表
						CurElem: 指定元素
* Output:				NextElem:单向链表中指定元素的后一个元素       
* Return:				false/true
**************************************************************************************/
bool NextElem(ListNode *&L, const Elemtype &CurElem, Elemtype &NextElem)
{
	bool bResult = false;
	ListNode *pCurNode = NULL;
	ListNode *pNextNode = NULL;

	if(2 <= ListLength(L))
	{
		pCurNode = L->pNext;
		pNextNode = L->pNext->pNext;
		while(NULL != pNextNode)
		{
			if(CurElem == pCurNode->Elem)
			{
				NextElem = pNextNode->Elem;
				bResult = true;
				break;
			}
			else
			{
				pCurNode = pCurNode->pNext;
				pNextNode = pNextNode->pNext;
			}
		}
	}
	return bResult;
}
/**************************************************************************************
* Author:				Sky	
* Functiuon:			GetElem()        
* Description:			返回单向链表中指定位序处的元素         
* Access Level:		NULL
* Input:				L: 单向链表
						i: 待获取的元素在单向链表中的位序
* Output:				Elem:单向链表中指定位序处的元素    
* Return:				fasle/true
**************************************************************************************/
bool GetElem(ListNode *&L, const int &i, Elemtype &Elem)
{
	bool bResult = false;
	ListNode *pCurNode = NULL;
	int j = 0;

	pCurNode = L;
	if(i>=1 && i<=ListLength(L))
	{
		for(j=0; j<i; j++)
		{
			pCurNode = pCurNode->pNext;
		}
		Elem = pCurNode->Elem;
		bResult = true;
	}
	return bResult;
}
/**************************************************************************************
* Author:				Sky	
* Functiuon:			ListEmpty()           
* Description:			判断单向链表是否为空链表         
* Access Level:		NULL
* Input:				L: 待判断单向链表头结点            
* Output:				NULL
* Return:				false: 该单向链表不是空链表
						true:  该单向链表是空链表
**************************************************************************************/
bool ListEmpty(ListNode *&L)
{
	bool bResult = false;
	ListNode *pCurNode = L;

	if(NULL == pCurNode->pNext)
		bResult = true;

	return bResult;
}
/**************************************************************************************
* Author:				Sky
* Functiuon:			ListLength()          
* Description:         返回指定单向链表的长度
* Access Level:		NULL
* Input:				L: 单向链表头结点
* Output:				NULL       
* Return:				单向链表长度       
**************************************************************************************/
int ListLength(ListNode *&L)
{
	ListNode *pCurNode = L->pNext;
	int Len = 0;

	while(NULL != pCurNode)
	{
		Len++;
		pCurNode = pCurNode->pNext;
	}
	return Len;
}
/**************************************************************************************
* Author:				Sky	
* Functiuon:			ListTravesal()          
* Description:         从头结点到尾节点遍历一个单向链表
* Access Level:		NULL
* Input:				L: 待遍历单向链表   
* Output:				NULL         
* Return:				NULL        
**************************************************************************************/
void ListTravesal(ListNode *&L)
{
	ListNode *pCurNode = L->pNext;

	while(NULL != pCurNode)
	{
		cout<<pCurNode->Elem<<endl;
		pCurNode = pCurNode->pNext;
	}
}
执行结果:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值