链表基本操作及部分面试题

链表基本操作

链表的定义
typedef int DataType;
typedef struct SListNode
{
	DataType data;         //当前节点中保存的元素
	struct SListNode* next;//指向链表中的下一个节点
}SListNode;
创建一个新的节点
SListNode* BuySListNode(DataType d)
{
	SListNode* newNode = (SListNode*)malloc(sizeof(SListNode));
	if (newNode == NULL)//创建不成功时
	{
		perror("BuySListNode::malloc");
		return NULL;
	}
	newNode->data = d;
	newNode->next = NULL;
	return newNode;
}
链表初始化
void SListInit(SListNode** pHead)
{
	assert(pHead);
	*pHead = NULL;
}
尾插
void SListPushBack(SListNode** pHead, DataType d)  //尾插
{
	//空链表,直接插入
	//非空链表,找最后一个结点
	assert(pHead);     //链表是否存在
	if (*pHead == NULL)//空链表时
	{
		*pHead = BuySListNode(d);
	}
	else//非空链表
	{
		SListNode*  pcur = *pHead;
		while (pcur->next != NULL)
			pcur = pcur->next;
		pcur->next = BuySListNode(d);
	}
}
尾删
void SListPopBack(SListNode** pHead)//尾删
{
	//空链表时
	//只有一个结点时
	//有两个及以上结点时
	assert(pHead);
	if (*pHead == NULL)
		return;
	else if ((*pHead)->next == NULL)
	{
		free(*pHead);
		*pHead = NULL;
	}
	else
	{
		SListNode*  pcur = *pHead;
		while (pcur->next->next)//找倒数第二个节点,把它的next置空
			pcur = pcur->next;
		free(pcur->next);
		pcur->next = NULL;
	}
}
头插
void SListPushFront(SListNode** pHead, DataType d)//头插
{
	SListNode* newNode = BuySListNode(d);
	assert(pHead);
	newNode->next = *pHead;
	*pHead = newNode;
}
头删
void SListPopFront(SListNode** pHead)//头删
{
	SListNode* pDel = NULL;
	assert(pHead);
	if (*pHead == NULL)
		return;
	else
	{
		pDel = *pHead;
		*pHead = pDel->next;
		free(pDel);
	}
}
销毁
void Destroy(SListNode** pHead)//销毁
{
	SListNode* pcur = *pHead;
	assert(pHead);
	while (pcur != NULL)
	{
		SListNode* del = pcur;
		pcur = pcur->next;
		free(del);
		del = NULL;
	}
	*pHead = NULL;
}

链表面试题

从尾至头打印
void PrintListFromTailToFront(SListNode* pHead)//从尾到头打印(递归)
{
	if (pHead)
	{
		PrintListFromTailToFront(pHead->next);
		printf("%d ", pHead->data);
	}
}
删除非尾节点
(伪删除法)
void DeleteListNotTail(SListNode* pos)//删除非尾结点(不能遍历链表)
{
	SListNode* pDel;
	if (pos == NULL || pos->next == NULL)
		return;
	pDel = pos->next;                //pos后面的数交给pos,删掉pos后面的节点
	pos->data = pDel->data;
	pos->next = pDel->next;
	free(pDel);
	pDel = NULL;
}
在指定位置前面插入
void InsertPosFront(SListNode* pos, DataType d)//在指定位置前面插入(不能遍历链表)                  
{
	SListNode* newNode;
	if (pos == NULL)
		return;
	newNode = BuySListNode(pos->data);//创建新节点(数据就为pos位置的数据)
	newNode->next = pos->next;      //插在pos位置的后面
	pos->next = newNode;
	pos->data = d;                  //然后将要插入的数据放在pos位置
}
查找指定数据的位置
SListNode* SListFind(SListNode* pHead, DataType d)//找
{
	SListNode* pCur = pHead;
	while (pCur)
	{
		if (pCur->data == d)
			return pCur;
		pCur = pCur->next;
	}
}
单链表排序(冒泡)
void BubbleSort(SListNode* pHead)//单链表排序(冒泡)
{
	SListNode* pTailNode = NULL;//定义尾部节点
	if (pHead == NULL || pHead->next == NULL)
		return;
	while (pHead != pTailNode)
	{
		SListNode* pPre = pHead;
		SListNode* pCur = pPre->next;
		while (pCur != pTailNode)
		{
			if (pPre->data>pCur->data)
			{
				DataType temp = pPre->data;
				pPre->data = pCur->data;
				pCur->data = temp;
			}
			pPre = pCur;
			pCur = pCur->next;
		}
		pTailNode = pPre;
	}
}
查找单链表中间结点,要求只遍历一次
SListNode* FindMiddleNode(SListNode* pHead)//查找中间结点,只遍历一次
{
	SListNode* pFast = pHead;
	SListNode* pSlow = pHead;
	while (pFast && pFast->next)
	{
		pFast = pFast->next->next;//一次移动两步
		pSlow = pSlow->next;//一次走一步
	}
	return pSlow;//pSlow不一定是中间位置,链表中节点个数可能是奇数(Fast->next是空的)或者偶数(Fast是空的)
}
查找倒数第k个,要求只遍历一次
SListNode* FindListNode(SListNode* pHead, DataType k)//查找倒数第k个
{
	SListNode* pFast = pHead;
	SListNode* pSlow = pHead;
	if (pHead == NULL || k <= 0)
		return NULL;
	while (k--)//先让fast走k步(也可以走k-1步,那就让fast走到倒数第二步)
	{
		if (pFast == NULL)
			return NULL;
		pFast = pFast->next;
	}
	while (pFast->next)//然后fast和slow一起走
	{
		pFast = pFast->next;
		pSlow = pSlow->next;
	}
	return pSlow;
}
逆置/反转单链表
void ReverseList(SListNode** pHead)//链表逆置
//第一种方法:三个指针
//第二种方法:将逆置链表中所有节点依次头插到新链表中
//(注意:PushFront()不能直接调用,除非该方法已经显示给出)
//如果链表带环呢?
{
	SListNode* pPre = NULL;
	SListNode* pCur = NULL;
	SListNode* pNext = NULL;
	assert(pHead);
	pCur = *pHead;
	while (pCur)
	{
		pNext = pCur->next;
		pCur->next = pPre;
		pPre = pCur;
		pCur = pNext;
	}
	*pHead = pPre;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值