// 倒叙打印链表
void ReversePrint(SListNode *pFirst);
// 逆置链表
SListNode * ReverseList(SListNode *pFirst);
// 删除非尾无头链表
void RemoveNodeNotTail(SListNode *pos);
// 无头链表前插入
void InsertNoHead(SListNode *pos, int data);
约瑟夫环
SListNode * JocephCircle(SListNode *pFirst, int k);
// 冒泡排序
void BubbleSort(SListNode *pFirst);
// 合并两个有序链表
SListNode * MergeOrderedList(SListNode *p1First, SListNode *p2First);
// 遍历一次,找到中间结点
SListNode * FindMid(SListNode *pFirst);
// 遍历一次,找到倒数第 k 个结点(k从1开始)
SListNode * FindK(SListNode *pFirst, int k);
验证后结果为:
具体实现看代码,代码如下:
Interview.h
#pragma once
#include "SList.h"
//从头到尾打印单链表
void Print(SListNode *pFirst){
SListNode *pNode = pFirst;
SListNode *end = NULL;
while (end != pFirst)
{
while (pNode->pNext != end)
{
pNode = pNode->pNext;
}
end = pNode;
printf("%d", pNode->data);
pNode = pFirst;
}
}
void Show(SListNode *p){
if (p->pNext){
Show(p->pNext);
}
printf("<- %d", p->data);
}
void TestPrintR(){
SListNode *pFirst = NULL;
printf("从头到尾打印单链表的结果是:5");
PushBack(&pFirst, 1);
PushBack(&pFirst, 2);
PushBack(&pFirst, 3);
PushBack(&pFirst, 4);
Show(pFirst);
printf("\n");
printf("\n");
}
//逆置单链表
SListNode *ReverseSList(SListNode *pFirst)
{
SListNode *pNewFirst = NULL;
DataType data;
while (pFirst != NULL)
{
data = pFirst->data;
PopFront(&pFirst); //头插
PushFront(&pNewFirst, data); //头删
}
return pNewFirst;
}
void TestReverse()
{
SListNode *pFirst = NULL;
printf("逆置单链表的结果是:");
PushBack(&pFirst, 1);
PushBack(&pFirst, 2);
PushBack(&pFirst, 3);
PushBack(&pFirst, 4);
PushBack(&pFirst, 5);
SListNode *pNewFirst = ReverseSList(pFirst);
Print(pNewFirst);
printf("\n");
printf("\n");
}
//删除无头链表的非尾节点 (不能遍历链表) 转换为删除pos指向的结点的下一个结点
//无头结点的链表:第一个节点既有数据域,又有指针域,是通过一个指向该链表的第一个节点的指针来标记该链表的,即可以成环。
void EraseNoFirstNotTail(SListNode *pPos)
{
assert(pPos != NULL);
SListNode *pNext = pPos->pNext;
pPos->pNext = pNext->pNext;
pPos->data = pNext->data;
free(pNext);
}
//在无头单链表的一个节点前插入一个节点(不能遍历链表)
void InsertNoFirst(SListNode *pPos, DataType data)
{
SListNode *pNewNode = (SListNode *)malloc(sizeof(SListNode));
assert(pNewNode != NULL);
pNewNode->data = pPos->data;
pNewNode->pNext = pPos->pNext;
pPos->data = data;
pPos->pNext = pNewNode;
}
void TestReplaceMethod()
{
SListNode *pFirst = NULL;
printf("插入节点后的结果是:");
PushBack(&pFirst, 1);
PushBack(&pFirst, 2);
PushBack(&pFirst, 3);
PushBack(&pFirst, 4);
PushBack(&pFirst, 5);
SListNode *pFound = Find(pFirst, 4);
InsertNoFirst(pFound, 7);
Print(pFirst);
printf("\n");
printf("\n");
printf("删除无头链表非尾节点7后的结果是:");
EraseNoFirstNotTail(pFound);
Print(pFirst);
printf("\n");
printf("\n");
}
//合并两个有序链表,合并后依旧有序
SListNode *MergeOrderedList(SListNode *p1First, SListNode *p2First)
{
SListNode *p1 = p1First;
SListNode *p2 = p2First;
SListNode *pNewFirst = NULL;
while (p1 != NULL&&p2 != NULL)
{
if (p1->data < p2->data)
{
PushBack(&pNewFirst, p1->data);
p1 = p1->pNext;
}
else
{
PushBack(&pNewFirst, p2->data);
p2 = p2->pNext;
}
}
SListNode *pNotEmpty = p1;
if (p1 == NULL)
{
pNotEmpty = p2;
}
while (pNotEmpty)
{
PushBack(&pNewFirst, pNotEmpty->data);
pNotEmpty = pNotEmpty->pNext;
}
return pNewFirst;
}
void TestMergeOrderedList()
{
SListNode *p1First = NULL;
PushBack(&p1First, 1);
PushBack(&p1First, 2);
PushBack(&p1First, 3);
PushBack(&p1First, 4);
printf("有序链表1的结果是:");
Print(p1First);
printf("\n");
SListNode *p2First = NULL;
PushBack(&p2First, 5);
PushBack(&p2First, 6);
PushBack(&p2First, 7);
PushBack(&p2First, 9);
printf("有序链表2的结果是:");
Print(p2First);
printf("\n");
SListNode *pMerged = MergeOrderedList(p1First, p2First);
printf("两个有序链表合并的结果是:");
Print(pMerged);
printf("\n");
printf("\n");
}
//约瑟夫环:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。
//从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,
//数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
//通常解决这类问题时我们把编号从0~n-1,最后 [1] 结果+1即为原问题的解。
SListNode *JocephCircle(SListNode *pFirst, int k)
{
SListNode *pNode = pFirst;
SListNode *pPrev = NULL;
int i;
while (pNode->pNext)
{
pNode = pNode->pNext;
}
pNode->pNext = pFirst;
pNode = pFirst;
while (pNode->pNext != pNode)
{
for (i = 0; i < k - 1; i++){
pPrev = pNode;
pNode = pNode->pNext;
}
pPrev->pNext = pNode->pNext;
free(pNode);
pNode = pPrev->pNext;
}
return pNode;
}
void TestJoceph()
{
SListNode *pFirst = NULL;
PushBack(&pFirst, 1);
PushBack(&pFirst, 2);
PushBack(&pFirst, 3);
PushBack(&pFirst, 4);
PushBack(&pFirst, 5);
PushBack(&pFirst, 6);
PushBack(&pFirst, 7);
printf("约瑟夫环为:");
Print(pFirst);
printf("\n");
printf("按3删除后的结果是:");
SListNode *pSuv = JocephCircle(pFirst, 3);
printf("%d\n", pSuv->data);
printf("\n");
}
//查找单链表的中间节点,要求只能遍历一次链表
//快慢指针
SListNode * FindMiddle(SListNode *pFirst)
{
assert(pFirst != NULL);
SListNode *pFast = pFirst;
SListNode *pSlow = pFirst;
while (1) {
pFast = pFast->pNext;
if (pFast == NULL) {
break;
}
pFast = pFast->pNext;
if (pFast == NULL) {
break;
}
pSlow = pSlow->pNext;
}
return pSlow;
}
void TestFindMiddle()
{
SListNode *pFirst = NULL;
PushBack(&pFirst, 1);
PushBack(&pFirst, 2);
PushBack(&pFirst, 3);
PushBack(&pFirst, 4);
PushBack(&pFirst, 1);
PushBack(&pFirst, 2);
PushBack(&pFirst, 3);
PushBack(&pFirst, 4);
PushBack(&pFirst, 5);
PushBack(&pFirst, 6);
PushBack(&pFirst, 7);
PushBack(&pFirst, 5);
PushBack(&pFirst, 6);
PushBack(&pFirst, 7);
printf("单链表是:");
Print(pFirst);
printf("\n");
SListNode *pFound = FindMiddle(pFirst);
printf("找到的中间结点是:");
printf("%d\n", pFound->data);
printf("\n");
}
void Swap(int* a, int* b) {
int tmp = *a;
*a = *b;
*b = tmp;
return;
}
//单链表实现冒泡排序
void BubbleSort(SListNode *pFirst)
{
SListNode *pCur = pFirst;
SListNode *pLast = pFirst;
if (pFirst == NULL){
return ;
}
for (pCur; pCur->pNext != NULL; pCur = pCur->pNext)
{
for (pLast;pLast ->pNext!=NULL ; pLast = pLast->pNext)
{
if (pLast->data < pLast->pNext->data)
{
int temp = pLast->data;
pLast->data = pLast->pNext->data;
pLast->pNext->data = temp;
}
}
}
return;
}
void TestBubbleSort()
{
SListNode *pFirst = NULL;
PushBack(&pFirst, 1);
PushBack(&pFirst, 9);
PushBack(&pFirst, 5);
PushBack(&pFirst, 4);
PushBack(&pFirst, 8);
PushBack(&pFirst, 2);
PushBack(&pFirst, 3);
printf("单链表是:");
Print(pFirst);
printf("\n");
BubbleSort(pFirst);
BubbleSort(pFirst);
BubbleSort(pFirst);
BubbleSort(pFirst);
BubbleSort(pFirst);
BubbleSort(pFirst);
printf("冒泡排序后的结果是:");
Print(pFirst);
printf("\n");
printf("\n");
}
// 遍历一次,找到倒数第 k 个结点
SListNode * FindK(SListNode *pFirst, int k){
if (k < 1 || pFirst ==NULL)
{
return NULL;
}
SListNode *pFast = pFirst;
SListNode *pSlow = pFirst;
for (int i = 0; i < k; i++)
{
if (pFast != NULL){
pFast = pFast->pNext;
}
else
{
return NULL;
}
}
while (pFast->pNext != NULL)
{
pFirst = pFirst->pNext;
pFast = pFast->pNext;
}
return pFirst;
}
void TestFindK()
{
SListNode *pFirst = NULL;
PushBack(&pFirst, 1);
PushBack(&pFirst, 2);
PushBack(&pFirst, 3);
PushBack(&pFirst, 4);
PushBack(&pFirst, 1);
PushBack(&pFirst, 2);
PushBack(&pFirst, 3);
PushBack(&pFirst, 4);
PushBack(&pFirst, 5);
PushBack(&pFirst, 6);
PushBack(&pFirst, 7);
PushBack(&pFirst, 5);
PushBack(&pFirst, 6);
PushBack(&pFirst, 7);
printf("尾插形成的单链表是:");
Print(pFirst);
printf("\n");
SListNode *pFound = FindK(pFirst,1);
printf("找到的下标为k的结点是:");
printf("%d\n", pFound->data);
printf("\n");
}
SList.h
#pragma once
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
//定义链表数据类型
typedef int DataType;
//定义链表数据结构
typedef struct SListNode{
DataType data; //当前节点中保存的元素
struct SListNode *pNext; //指向链表的下一个结点
}SListNode;
//链表初始化
void SListInit(SListNode **ppFirst)
{
assert(ppFirst != NULL); //assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行
*ppFirst = NULL;
}
//链表销毁
void SListDestroy(SListNode **ppFirst){
assert(ppFirst != NULL);
SListNode *pNode, *pNext;
pNode = *ppFirst;
while (pNode != NULL){
pNext = pNode->pNext;
free(pNode); //void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针。
//如果分配失败,则返回一个空指针(NULL)。关于分配失败的原因,应该有多种,比如说空间不足就是一种。
//void free(void *FirstByte): 该函数是将之前用malloc分配的空间还给程序或者是操作系统,
//也就是释放了这块内存,让它重新得到自由.free()释放的是指针指向的内存!
pNode = pNext;
}
*ppFirst = NULL;
}
//创建新结点
SListNode *CreateNewNode(int data)
{
SListNode *pNewNode = (SListNode*)malloc(sizeof(SListNode)); //malloc()是从堆里面获得空间。也就是说函数返回的指针是指向堆里面的一块内存。
assert(pNewNode);
pNewNode->data = data;
pNewNode->pNext = NULL;
return pNewNode;
}
//尾插
void PushBack(SListNode **ppFirst, DataType data)
{
assert(ppFirst != NULL);
SListNode *pNewNode = CreateNewNode(data);
if (*ppFirst == NULL)
{
*ppFirst = pNewNode;
return;
}
SListNode *pNode;
pNode = *ppFirst;
while (pNode->pNext != NULL)
{
pNode = pNode->pNext;
}
pNode->pNext = pNewNode;
}
//头插
void PushFront(SListNode **ppFirst, DataType data)
{
assert(ppFirst != NULL);
SListNode *pNewNode = CreateNewNode(data);
pNewNode->pNext = *ppFirst;
*ppFirst = pNewNode;
}
//头删
void PopFront(SListNode **ppFirst)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL);
SListNode *pOldFirst = *ppFirst;
*ppFirst = (*ppFirst)->pNext;
free(pOldFirst);
}
SListNode * Find(SListNode *pFirst, DataType data)
{
SListNode *pNode;
for (pNode = pFirst; pNode; pNode = pNode->pNext) {
if (pNode->data == data) {
return pNode;
}
}
return NULL;
}
Main.cpp
#include "Interview.h"
int main(void)
{
TestPrintR();
TestReverse();
TestReplaceMethod();
TestMergeOrderedList();
TestJoceph();
TestFindMiddle();
TestBubbleSort();
TestFindK();
system("pause");
}