C语言实现单链表

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

typedef int DataType;
typedef struct Node
{
	DataType data;//数据域
	struct Node* next;//保存下一个节点地址的指针域
}Node,*PNode;

void InitList(PNode* pHead)//初始化 传二级指针
{
	assert(pHead);
	*pHead = NULL;
}

PNode BuyNode(DataType data)//申请新节点
{
	PNode pTemp = (PNode)malloc(sizeof(Node));//申请空间
	if(pTemp)//空间申请成功,若不成功直接返回NULL
	{
		pTemp->data = data;
		pTemp->next = NULL;
	}
	return pTemp;
}
void PushBack(PNode* pHead, DataType data)//尾插
{
	assert(pHead);
	if(*pHead == NULL)//空链表
	{
		*pHead = BuyNode(data);
	}
	else//链表不为空
	{
		PNode pcur = *pHead;
		while(pcur->next)
		{
			pcur = pcur->next;
		}
		pcur->next = BuyNode(data);
	}
}
void PopBack(PNode* pHead)//尾删
{
	assert(pHead);
	if(*pHead == NULL)//链表为空
	{
		return;
	}
	else if((*pHead)->next == NULL)//链表只有一个节点
	{
		free(*pHead);
		*pHead = NULL;
	}
	else//链表有多个节点
	{
		PNode pcur = *pHead;
		PNode pre = pcur;
		while(pcur->next)
		{
			pre = pcur;
			pcur = pcur->next;
		}
		free(pcur);
		pre->next = NULL;
	}
}
void PrintList(PNode pHead)//正序打印 不需二级指针,不改变外部实参
{
	PNode pcur = pHead;
	while(pcur)
	{
		printf("%d->",pcur->data);
		pcur = pcur->next;
	}
	printf("NULL\n");
}
///面试题1//单链表逆置打印 递归//
void PrintTail2Head(PNode pHead)
{
	if(pHead)
	{
		PrintTail2Head(pHead->next);
		printf("%d->",pHead->data);
	}
}
void PushFront(PNode* pHead, DataType data)//头插
{
	assert(pHead);
	if(*pHead == NULL)//空链表与下面的非空情况可以合并到一起
	{
		*pHead = BuyNode(data);
	}
	else
	{
		PNode newnode = BuyNode(data);
		if(newnode)//必须判断新节点是否创建成功,成功才可以插入
		{
			newnode->next = *pHead;//先将节点链接起来,否则可能丢失原链表
		    *pHead = newnode;//然后让第一个节点的指针再指向新节点
		}
	}
}
void PopFront(PNode* pHead)//头删
{
	assert(pHead);
	if(pHead == NULL)//分两种情况 链表为空
	{
		return;
	}
	//非空
	else
	{
	    PNode pTemp = *pHead;//先保存第一个节点
	    *pHead = (*pHead)->next;//再让第一个节点向后移动
	    free(pTemp);//释放掉第一个节点
	    pTemp = NULL;
	}
}
PNode Find(PNode pHead, DataType data)//查找data元素的位置
{
	PNode pTemp = pHead;
	while(pTemp)
	{
		if(pTemp->data == data)
		{
			return pTemp;
		}
		pTemp = pTemp->next;
	}
	return NULL;//不存在返回空
}
void Insert(PNode pos, DataType data)//在pos位置后插入元素
{
	PNode newnode = NULL;//为啥要先赋空???
	if(pos == NULL)//插入位置是否合法
	{
		return;
	}
    newnode = BuyNode(data);//先申请新节点
	newnode->next = pos->next;//让新节点的next指向pos的next
	pos->next = newnode;//然后让pos的next指向新节点
}
void Erase(PNode* pHead, PNode pos)//要给出外部头指针。因为pos若为头结点 有可能改变头结点的值
{
	assert(pHead);//链表是否存在
	if(pHead == NULL || pos == NULL)//链表为空或位置不合法
	{
		return;
	}

	if(pos == *pHead)//删除位置为头结点
	{
		*pHead = pos->next;//头结点后移
		free(pos);//删除头节点
	}
	else
	{
		PNode pcur = *pHead;
		while(pcur->next != pos)
		{
			pcur = pcur->next;
		}
		pcur->next = pos->next;
		free(pos);
	}
}
/面试题2删除非尾节点,不能遍历链表 其实是删除pos的下一个节点//
void DelNotTail(PNode pos)
{
	PNode Delnode =NULL;
	if(NULL == pos || pos->next ==NULL)
		return;
	Delnode = pos->next;
	pos->data = Delnode->data;
	pos->next = Delnode->next;
	free(Delnode);
}
/面试题3/在非头结点前插入元素(头结点也可以) 在pos后插 然后交换值///
void InsertNotHead(PNode pos, DataType data)
{
	PNode newnode = NULL;//?????????
	if(pos == NULL)
		return;
	newnode = BuyNode(pos->data);
	if(newnode)//必须判断节点是否申请成功
	{
		newnode->next = pos->next;
	    pos->next = newnode;
		pos->data = data;
	}
} 
void Remove(PNode pHead, DataType data)//删除值为data的元素,直接调用Erase函数(传引用)与Find函数(不传引用)
{
	assert(pHead);
	Erase(&pHead, Find(pHead, data));
}
void RemoveAll(PNode* pHead, DataType data)//删除所有值为data的元素!!!!!!!!!!!!!!!!!!!!!有问题
{
	PNode pcur = NULL;
	PNode pre = NULL;
	assert(pHead);//链表是否存在

	pre = *pHead;//定义两个指针 一个指向第一个节点
	pcur = pre->next;//指向第二个节点

	while(pcur)//遍历一遍单链表
	{
		if(pcur->data == data)//若pcur指向的节点值为data
		{
			pre->next = pcur->next;
			free(pcur);//释放pcur
			//pcur = pre;//让pcur指向前一个
			pcur = pre->next;
		}
		else
		{
			pcur = pcur->next;
		}
		
	
	}

	if((*pHead)->data == data)//如果头节点值为data的情况
	{
		pcur = *pHead;
		*pHead = (*pHead)->next;
		free(pcur);
	}
}

size_t Size(PNode pHead)//链表中元素个数
{
	PNode pcur = NULL;
	int count = 0;

	assert(pHead);
	pcur = pHead;
	while(pcur)
	{
		count++;
		pcur = pcur->next;
	}
	return count;
}
//PNode Front(PNode pHead)
//{
//	assert(pHead);
//	return pHead;
//}
PNode Back(PNode pHead)
{
	PNode pcur = pHead;
	if(NULL == pHead)
          return NULL;
	while(pcur->next)
	{
		pcur = pcur->next;
	}
	return pcur;
}
//int Empty(PNode pHead);
//面试题//约瑟夫环/
PNode JosephCircle(PNode pHead, size_t M)
{
	PNode pCur = pHead;
	PNode pTemp = NULL;
	if(pHead == NULL)
		return NULL;
	while(pCur->next != pCur)
	{
		size_t count = M;
		while(--count)
		{
			pCur = pCur->next;
		}
		pTemp = pCur->next;
		pCur->data = pTemp->data;
		pCur->next = pTemp->next;
		free(pTemp);
	}
	return pCur;
}
//测试
void FunTest4()
{
	PNode pHead, pos;
	int count = 0;
	InitList(&pHead);
	PushBack(&pHead, 1);
	PushBack(&pHead, 2);
	PushBack(&pHead, 3);
	PushBack(&pHead, 4);
	PushBack(&pHead, 5);

	//Erase(&pHead, Find(pHead, 3));
	//Remove(pHead, 2);
	//RemoveAll(&pHead, 2);///有问题啊
/约瑟夫环//
	pos = Back(pHead);//构环
	pos->next = pHead;//构环
	pHead = JosephCircle(pHead, 3);
	pHead->next = NULL;
	PrintList(pHead);

	
	//count = Size(pHead);
	//printf("%d\n",count);
}

void FunTest()
{
	PNode pHead;
	InitList(&pHead);
	PushBack(&pHead, 1);
	PushBack(&pHead, 2);
	PushBack(&pHead, 3);
	PushBack(&pHead, 4);
	PrintList(pHead);
	PushFront(&pHead, 5);
	PrintList(pHead);
	PrintTail2Head(pHead);

	PopBack(&pHead);
	PrintList(pHead);

	PopBack(&pHead);
	PopBack(&pHead);
	PrintList(pHead);

	PopBack(&pHead);
	PrintList(pHead);

	PopBack(&pHead);
	PrintList(pHead);

}

void FunTest1()
{
	PNode pHead;
	InitList(&pHead);
	PushFront(&pHead, 1);
	PushFront(&pHead, 2);
	PushFront(&pHead, 3);
	PushFront(&pHead, 4);
	PrintList(pHead);
	PopFront(&pHead);
	PrintList(pHead);
	PrintTail2Head(pHead);
}

void FunTest2()
{
	PNode pHead, pos;
	InitList(&pHead);
	PushBack(&pHead, 1);
	PushBack(&pHead, 2);
	PushBack(&pHead, 3);
	PushBack(&pHead, 4);
	pos = Find(pHead, 2);
	Insert(pos,5);
	PrintList(pHead);
	Erase(&pHead, Find(pHead, 5));
	PrintList(pHead);

	Erase(&pHead, Find(pHead, 1));
	PrintList(pHead);

	DelNotTail(Find(pHead, 2));///只能删除非尾节点
	PrintList(pHead);
}

void FunTest3()
{
	PNode pHead;
	InitList(&pHead);
	PushBack(&pHead, 1);
	PushBack(&pHead, 2);
	PushBack(&pHead, 3);
	PushBack(&pHead, 4);
	PrintList(pHead);
	InsertNotHead(Find(pHead, 2),5);
	PrintList(pHead);
}

int main()
{
	FunTest4();
	system("pause");
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值