单链表中一些经典的问题-->约瑟夫环,链表逆序,查找链表结点...(上)

上篇博客中写了关于单链表的一些基本操作,接下来是对单链表的一些扩展问题,接下来实现如下问题:

     ---->从尾到头打印单链表--->删除链表的非尾结点,不遍历链表--->约瑟夫环--->使用冒泡方式对单链表进行排序--->单链表的逆序---(三个指针)---->单链表的逆序---(使用头插法)--->合并两个有序链表,合并起来依然要有序--->查找链表的中间结点,只遍历一次链表--->查找链表的倒数第K个结点等等。

下面用C语言代码实现

    slist.c

 
 
//从尾到头打印单链表
void PrintSlistTail(pNode pHead)  //递归方式
{
	if (pHead)
	{
		PrintSlistTail(pHead->_pNext);
		printf("%d-->", pHead->_data);
	}
}


// 删除链表的非尾结点,要求不能遍历链表 
void DeleteNotTailNode( pNode pos) //替换法
{
	pNode pCur = NULL;
	if (NULL == pos || NULL == pos->_pNext)
	{
		return;
	}
	pCur=pos->_pNext;
	pos->_data=pos->_pNext->_data;
	pos->_pNext = pos->_pNext->_pNext;  
	free(pCur);                //释放结点
}




// 约瑟夫环 
void JosephCirclePre(pNode *pHead)  //构成环
{
	assert(pHead);
	pNode pCur = NULL;
	if (*pHead == NULL)
	{
		return;
	}
    pCur = *pHead;
	while (pCur->_pNext)
	{
		pCur = pCur->_pNext;
	}
	pCur->_pNext = *pHead;
}
void JosephCircle(pNode* pHead, const int M)  //删除结点
{
	assert(pHead);
	pNode pCur = NULL;
	int count = 0;
	if (*pHead == NULL)
	{
		return;
	}
	pCur = *pHead;
	while (pCur!=pCur->_pNext)
	{
		count = M;
		while (--count)
		{
			pCur = pCur->_pNext;
		}
		pCur->_data = pCur->_pNext->_data;
		pCur->_pNext = pCur->_pNext->_pNext;
	}
	pCur->_pNext = NULL;
	*pHead = pCur;
}
// 使用冒泡方式对单链表进行排序 
void BubbleSort(pNode pHead)
{
	assert(pHead);
	int i = 0;
	int j = 0;
	pNode pCur =NULL;
	int size = SListSize(pHead);
	for (i = 0; i < size-1; i++)
	{
		 pCur = pHead;
		for (j = 0; j < size - 1 - i; j++)
		{
			if ((pCur->_data)>(pCur->_pNext->_data))
			{
				int tmp = pCur->_data;
				pCur->_data = pCur->_pNext->_data;
				pCur->_pNext->_data = tmp;
			}
			pCur = pCur->_pNext;
		}
	}
}

// 单链表的逆序---三个指针 
void ReverseSList(pNode* pHead)
{
	assert(pHead);
	pNode pPre = NULL;
	pNode pCur = NULL;
	pNode pNext = NULL;
	if (*pHead == NULL)
	{
		return;
	}
	pCur = *pHead;
	while (pCur)
	{
		pNext=pCur->_pNext;
		pCur->_pNext = pPre;
		pPre = pCur;
		pCur = pNext;
	}
	*pHead = pPre;
}

// 单链表的逆序---使用头插法 
pNode ReverseSListOP(pNode pHead)
{
	pNode pNewNode=NULL;
	pNode pCur = pHead;
	while (pCur)
	{
		SListPushFront(&pNewNode, pCur->_data);
		pCur = pCur->_pNext;
	}
	return pNewNode;
}

// 合并两个有序链表,合并起来依然要有序 
pNode MergeSList(pNode pHead1, pNode pHead2)
{
	pNode pNewNode = NULL;
	pNode pCur1 =NULL;
	pNode pCur2 = NULL;
	if (pHead1 == NULL)  //判空
	{
		return pHead2;
	}
	else if (pHead2 == NULL)
	{
		return pHead1;
	}
	pCur1 = pHead1;
	pCur2 = pHead2;
	while (pCur1!=NULL && pCur2!=NULL)
	{
		if ((pCur1->_data) < (pCur2->_data))
		{
			sListPushBack(&pNewNode, pCur1->_data);
			pCur1 = pCur1->_pNext;
		}
		else 
		{
			sListPushBack(&pNewNode, pCur2->_data);
			pCur2 = pCur2->_pNext;
		}
}
	if (pCur1==NULL &&pCur2!=NULL)
	{
		while (pCur2)
		{
			sListPushBack(&pNewNode, pCur2->_data);
			pCur2 = pCur2->_pNext;
		}
	}
	if (pCur2==NULL && pCur1!=NULL)
	{
		while (pCur1)
		{
			sListPushBack(&pNewNode, pCur1->_data);
			pCur1 = pCur1->_pNext;
		}
	}
	return pNewNode;
}

// 查找链表的中间结点,要求只能遍历一次链表 
pNode FindMiddleNode(pNode pHead)
{
	assert(pHead);
	pNode pCur = pHead;
	pNode pSlow = pCur;
	pNode pFast = pCur;
	
	while (pFast!=NULL && pFast->_pNext!=NULL)
	{
		pFast = pFast->_pNext->_pNext;
		pSlow = pSlow->_pNext;
	}
	return pSlow;
}

// 查找链表的倒数第K个结点(遍历一次链表) 
pNode FindLastKNode(pNode pHead, int K)
{
	assert(pHead);
	pNode pCur = pHead;
	pNode pFast = pHead;
	pNode pSlow = pHead;
	if (K < 0 || K>SListSize(pCur))
	{
		return NULL;
	}
	while (K--)
	{
		pFast = pFast->_pNext;
	}
	while (pFast!=NULL)
	{
		pFast = pFast->_pNext;
		pSlow = pSlow->_pNext;
	}
	return pSlow;
}


test.c

 
 
#include "slist.h"
//测试尾插
void testsListPushBack(pNode *pHead)
{
	sListPushBack(pHead, 1);
	sListPushBack(pHead, 2);
	sListPushBack(pHead, 3);
	sListPushBack(pHead, 4);
	printSList(*pHead);
	printNodeNum(*pHead);
}
//测试从尾到头打印单链表
void testPrintSlistTail(pNode pHead)
{
	PrintSlistTail(pHead); 
}
//测试 删除链表的非尾结点,要求不能遍历链表
void testDeleteNotTailNode(pNode pHead)
{
	DeleteNotTailNode(pHead->_pNext);
	printSList(pHead);
}
// 测试约瑟夫环 
void testJosephCircle(pNode *pHead)     
{
	JosephCircle(pHead, 3);
}

void testJosephCirclePre(pNode *pHead)   //测试是否成环
{
	JosephCirclePre(pHead);
	testJosephCircle(pHead);    //测试删除结点是否成功,解环
	printSList(*pHead);
}

//测试单链表的逆序---三个指针
void testReverseSList(pNode *pHead)
{
	ReverseSList(pHead);
	printSList(*pHead);
}

// 测试单链表的逆序---使用头插法
void testReverseSListOP(pNode pHead)
{
	pNode pCur=ReverseSListOP(pHead);
	printSList(pCur);
}
// 测试合并两个有序链表,合并起来依然要有序 
void testMergeSList(pNode pHead1,pNode pHead2)
{
	pNode pCur=MergeSList(pHead1, pHead2);
	printSList(pCur);
}
// 查找链表的中间结点,要求只能遍历一次链表 
void testFindMiddleNode(pNode pHead)
{
	pNode pCur=FindMiddleNode(pHead);
}

void testFindLastKNode(pNode pHead)
{
	pNode pCur = FindLastKNode(pHead, 1);
}
int main()
{
	pNode pHead;
	pNode pHead2;
	sListInit(&pHead);
	sListInit(&pHead2); 
	testsListPushBack(&pHead);
	testsListPushBack(&pHead2);
	testPrintSlistTail(pHead);
	testDeleteNotTailNode(pHead);
	testJosephCirclePre(&pHead);
	testReverseSList(&pHead);
	testReverseSListOP(pHead);
	testMergeSList(pHead, pHead2);
	testFindMiddleNode(pHead);
	testFindLastKNode(pHead);
	system("pause");
	return 0;
}



slist.h

#define _CRT_SECURE_NO_WARNINGS 0;
#pragma once
typedef int DataType; 
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef struct SListNode
{
	struct SListNode* _pNext; //指向链表的的下一个结点
	DataType _data; //当前结点中所保存的元素
}Node,*pNode;


void PrintSlistTail(pNode pHead);
void DeleteNotTailNode(pNode pos);

void JosephCirclePre(pNode *pHead);
void JosephCircle(pNode* pHead, const int M);
void BubbleSort(pNode pHead);
void ReverseSList(pNode* pHead);
pNode ReverseSListOP(pNode pHead);
pNode MergeSList(pNode pHead1, pNode pHead2);
pNode FindMiddleNode(pNode pHead);
pNode FindLastKNode(pNode pHead, int K);
在上面可能会涉及到一些对单链表删除,插入的基本操作,已发在上篇博客(单链表的一些基本操作),在这里就不详述。



猜你喜欢

转载自blog.csdn.net/eternal_01/article/details/79715670