上篇博客中写了关于单链表的一些基本操作,接下来是对单链表的一些扩展问题,接下来实现如下问题:
---->从尾到头打印单链表--->删除链表的非尾结点,不遍历链表--->约瑟夫环--->使用冒泡方式对单链表进行排序--->单链表的逆序---(三个指针)---->单链表的逆序---(使用头插法)--->合并两个有序链表,合并起来依然要有序--->查找链表的中间结点,只遍历一次链表--->查找链表的倒数第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);
在上面可能会涉及到一些对单链表删除,插入的基本操作,已发在上篇博客(单链表的一些基本操作),在这里就不详述。