单链表基本操作

每天进步一点点!


单链表的我插入、删除、查找、、、


头文件声明:

#ifndef __LINKLIST__
#define __LINKLIST__

#include <stdio.h>
#include <windows.h>
#include <assert.h>

#pragma warning(disable:4996)

//实现无头单链表的如下操作

typedef int DataType;

typedef struct Node
{
	struct Node* next;
	DataType data;
}Node, *PNode;


/
// 初始化单链表---思考为什么要传递二级指针
void InitList(PNode* pHead);

// 在链表尾部插入值为data的新结点
void PushBack(PNode* pHead, DataType data);

// 删除链表的最后一个节点
void PopBack(PNode* pHead);

// 在链表头部插入置为data的新节点
void PushFront(PNode* pHead, DataType data);

// 删除链表的第一个结点
void PopFront(PNode* pHead);

// 查找链表中值为data的结点,存在返回该结点的地址,否则返回空
PNode Find(PNode pHead, DataType data);

//在链表pos位置后插入值为data的新节点
void Insert(PNode pos, DataType data);

// 删除单链表pos位置上的结点
void Erase(PNode* pHead, PNode pos);

// 移除链表中第一个值为data的结点
void Remove(PNode* pHead, DataType data);

// 移除链表中所有值为data的结点
void RemoveAll(PNode* pHead, DataType data);

// 获取链表中结点的总个数
size_t Size(PNode pHead);

// 获取链表中第一个结点
PNode Front(PNode pHead);

// 获取链表中最后一个节点
PNode Back(PNode pHead);

// 判断链表是否为空
int Empty(PNode pHead);

// 打印单链表
void PrintList(PNode pHead);

// 构建新节点
PNode BueNode(DataType data);

链表面试题
// 从尾到头打印单链表
void PrintListFromTail(PNode pHead);

// 删除无头单链表的非尾结点,要求:不能遍历单链表
void DelectNotTailNode(PNode* pHead, PNode pos);
 
// 在无头单链表非头结点前插入新节点
void InsertNotHeadNode(PNode pos, DataType data);


#endif


函数实现:

#include "LinkList.h"

///
// 初始化单链表---思考为什么要传递二级指针?      //
//(使用一级指针,调用函数时形参压栈,函数结束时,/
// 形参会随之释放,期间对其参数的所有操作都无效。//
///

//初始化单链表
void InitList(PNode* pHead)
{
	assert(pHead);
	*pHead = NULL;
}

// 构建新节点
PNode BuyNode(DataType data)
{
	//申请内存
	PNode pNewNode = (PNode)malloc(sizeof(Node));
	if(NULL == pNewNode){
		perror("malloc");
		exit(1);
	}

	pNewNode->data = data;
	pNewNode->next = NULL;

	return pNewNode;
}

// 在链表尾部插入值为data的新结点
void PushBack(PNode* pHead, DataType data)
{
	PNode pCur = *pHead;

	assert(pHead);

	//链表为空则直接插入
	if(NULL == *pHead){
		*pHead = BuyNode(data);
	}
	else{
		//否则寻找尾节点
		while(pCur->next){
			pCur = pCur->next;
		}
		//插入
		pCur->next = BuyNode(data);
	}
}

// 删除链表的最后一个节点
void PopBack(PNode* pHead)
{
 	PNode pCur = *pHead;
	PNode pTail = NULL;

	assert(pHead);

	//若链表为空则返回
	if(NULL == *pHead){
		return ;
	}
	//若只有一个节点
	else if(NULL == (*pHead)->next){
		free(*pHead);
		*pHead = NULL;
	}
	else{
		//节点个数大于一
		//寻找倒数第二个节点
		while(pCur->next->next){
			pCur = pCur->next;
		}
		pTail = pCur->next;//记录尾节点
		free(pTail);//释放尾节点
		pCur->next =NULL;
	}
}

// 在链表头部插入置为data的新节点
void PushFront(PNode* pHead, DataType data)
{
	PNode pNewHead = BuyNode(data);

	pNewHead->next = *pHead;
	*pHead = pNewHead;
}

// 删除链表的第一个结点//
void PopFront(PNode* pHead)
{
	PNode pDelNode = NULL;

	assert(pHead);

	if(NULL == *pHead){
		return ; 
	}
	else{
		pDelNode = *pHead;
		*pHead = (*pHead)->next;
		free(pDelNode);
	}
}

// 查找链表中值为data的结点,存在返回该结点的地址,否则返回空
PNode Find(PNode pHead, DataType data)
{
	PNode pCur = pHead;

	//遍历查找
	while(pCur){
		if(data == pCur->data){
			return pCur;
		}
		pCur = pCur->next;
	}		

	return NULL;
}

//在链表pos位置后插入值为data的新节点
void Insert(PNode pos, DataType data)
{
	PNode pNewNode = NULL;

	if(NULL == pos){
		return ;
	}

	pNewNode = BuyNode(data);
	pNewNode->next = pos->next;
	pos->next = pNewNode;
}

// 删除单链表pos位置上的结点
void Erase(PNode* pHead, PNode pos)
{
	PNode pPreNode = NULL;

	assert(pHead);

	if(NULL == *pHead || NULL == pos){
		return ;
	}
	//若待删节点为头结点则特殊处理
	if(pos == *pHead){
		(*pHead) = pos->next;
		free(pos);
	}
	//找到待删节点的下一个节点
	else{
		pPreNode = *pHead;
		while(pos != pPreNode->next){
			pPreNode = pPreNode->next;
		}
		pPreNode->next = pos->next;
		free(pos);
	}
}

// 移除链表中第一个值为data的结点
void Remove(PNode* pHead, DataType data)
{
	assert(pHead);

	Erase(pHead, Find(*pHead, data));
}

// 移除链表中所有值为data的结点
void RemoveAll(PNode* pHead, DataType data)
{
	PNode pDelNode = NULL;
	PNode pPreNode = NULL;

	pPreNode = *pHead;
	pDelNode = (*pHead)->next;

	assert(pHead);

	//先从第二个节点开始处理
	while(pDelNode){
		if(pDelNode->data == data){
			pPreNode->next = pDelNode->next;
			free(pDelNode);
			pDelNode = pPreNode;
		}
		pPreNode = pDelNode;
		pDelNode = pDelNode->next;
	}

	//结束后再处理第一个节点
	if((*pHead)->data == data){
		pDelNode = *pHead;
		*pHead = pDelNode->next;
		free(pDelNode);
	}
}



// 获取链表中结点的总个数
size_t Size(PNode pHead)
{
	size_t num = 0;
	PNode pCur = pHead;

	while(pCur){
		num++;
		pCur = pCur->next;
	}

	return num;
}

// 获取链表中第一个结点
PNode Front(PNode pHead)
{
	return pHead;
}

// 获取链表中最后一个节点
PNode Back(PNode pHead)
{
	PNode pCur = pHead;

	//若为空直接返回
	if(NULL == pHead){
		return NULL;
	}

	//不空则遍历
	else{
		while(pCur->next)
		{
			pCur = pCur->next;
		}
		return pCur;
	}
}

// 判断链表是否为空
int Empty(PNode pHead)
{
	if(NULL == pHead){
		return 1;
	}
	else{
		return 0;

	}
}

// 打印单链表
void PrintList(PNode pHead)
{
	PNode pCur = pHead;

	while(pCur){
		printf("%d->", pCur->data);
		pCur = pCur->next;
	}
	printf("NULL\n");
}

链表面题///

//逆序打印
void PrintListFromTail(PNode pHead)
{
	//递归
	if(pHead->next){
		PrintListFromTail(pHead->next);
	}
	printf("%d->", pHead->data);
}

//删除非尾节点
void DelectNotTailNode(PNode* pHead, PNode pos)
{
	PNode posNextNode = NULL;

	if(NULL == pos || NULL == pos->next){
		return;
	}
	//将待删节点后一个节点data域赋给待删节点,再删除后面的节点
	posNextNode = pos->next;
	pos->data = posNextNode->data;
	pos->next = posNextNode->next;
	free(posNextNode);
}

//在非头节点前插入
void InsertNotHeadNode(PNode pos, DataType data)
{
	PNode pNewNode = NULL;

	if(NULL == pos){
		return ;
	}

	//插到该节点的后面,再将该节点与其交换
	pNewNode = BuyNode(pos->data);
	pNewNode->next = pos->next;
	pos->next = pNewNode;
	pos->data = data;
}



成于坚持,败于止步!


【作者:果冻 http://blog.csdn.net/jelly_9

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值