链表面试题

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#include <assert.h>

typedef int DataType;
typedef struct ListNode{
	DataType data;
	struct ListNode *pNext;
}	ListNode;

ListNode *NewSpace(DataType data)
{
	ListNode *pNode = (ListNode *)malloc(sizeof(ListNode));
	assert(pNode);
	pNode->data = data;
	pNode->pNext = NULL;

	return pNode;
}

void ListInit(ListNode **pListHead)
{
	(*pListHead) = NewSpace(-1);
	(*pListHead)->pNext = NULL;
}

void InsertFront(ListNode **pListHead, DataType data)
{
	assert(*pListHead);
	ListNode *pNode = NewSpace(data);

	if ((*pListHead)->data == -1){
		(*pListHead)->data = data;
		return;
	}

	pNode->pNext = (*pListHead);
	(*pListHead) = pNode;

	return;
}

void InsertBack(ListNode **pListHead, DataType data)
{
	assert(*pListHead);
	ListNode *pNode = NewSpace(data);
	ListNode *pInsert = (*pListHead);

	if ((*pListHead)->data == -1){
		(*pListHead)->data = data;
		return;
	}

	while (pInsert->pNext){
		pInsert = pInsert->pNext;
	}
	pInsert->pNext = pNode;
}

//找第k个结点
ListNode *FindKthTotail(ListNode *pListHead, int k)
{
	assert(pListHead);

	int iTotal = 0;
	int iFind = 0;
	ListNode *pFind = pListHead;

	while (pFind){
		iTotal++;
		pFind = pFind->pNext;
	}
	//printf("%d  \n", iTotal);

	iFind = iTotal - k + 1;
	pFind = pListHead;
	while (iFind--){
		pFind = pFind->pNext;
	}

	printf("第%d个结点的值:%d	地址:%p\n", k, pFind->data, pFind);

	return pFind;
}

//头删
void DelFront(ListNode **pListHead)
{
	assert(*pListHead);

	ListNode *pDel = (*pListHead);
	(*pListHead) = (*pListHead)->pNext;

	free(pDel);
	pDel = NULL;
}

//尾删
void DelBack(ListNode **pListHead)
{
	assert(*pListHead);

	if ((*pListHead)->pNext == NULL){
		free(*pListHead);
		pListHead = NULL;
		return;
	}

	ListNode *pDel = (*pListHead);

	while (pDel->pNext->pNext){
		pDel = pDel->pNext;
	}
	free(pDel->pNext);
	pDel->pNext = NULL;
}

void SimpListPrint(ListNode *pListHead)
{
	assert(pListHead);

	ListNode *pPri = pListHead;

	while (pPri){
		printf("%-3d", pPri->data);
		pPri = pPri->pNext;
	}
	printf("\n");
}

//删除一个无头单链表的非尾节点(不能遍历链表)
void DelPos(ListNode **pListHead, ListNode *pPos)
{
	assert(*pListHead);
	assert(pPos);
	assert(pPos->pNext);	//非尾

	ListNode *pDel = pPos->pNext;

	pPos->data = pDel->data;
	pPos->pNext = pDel->pNext;
	free(pDel);
	pDel = NULL;
}

//在无头单链表的一个节点前插入一个节点(不能遍历链表)
void InsertPosFront(ListNode **pListHead, ListNode *pPos, DataType data)
{
	//先插到这个结点后面,再交换
	assert(*pListHead);

	ListNode *pNode = NewSpace(data);
	pNode->pNext = pPos->pNext;
	pPos->pNext = pNode;

	DataType tmp = *(&pPos->data);
	*(&pPos->data) = *(&pNode->data);
	*(&pNode->data) = tmp;
}

//单链表实现约瑟夫环(JosephCircle)
void JosephCircle(ListNode *pListHead, int k)
{
	//这是一个环形链表
	assert(pListHead);
	
	ListNode *pList = pListHead;
	ListNode *pPre = pListHead;
	int i = k;

	while (pList->pNext != pListHead){
		i = k;
		while (i--){
			pPre = pList;
			pList = pList->pNext;
		}
		pPre->pNext = pList->pNext;
		free(pList);
		pList = pPre->pNext;
	}
}


//逆置/反转单链表
void Reverse(ListNode **pListHead)
{
	//或者重新定义一个链表  从头遍历旧链表  每个节点用头插法插到新链表
	assert(*pListHead);
	ListNode *pNewList;
	ListInit(&pNewList);
	ListNode *pList = (*pListHead);

	while (pList){
		InsertFront(&pNewList, pList->data);
		pList = pList->pNext;
	}

	free(*pListHead);
	(*pListHead) = pNewList;
}


//单链表排序(冒泡排序&快速排序) 
void Swap(DataType *a, DataType *b)
{
	DataType tmp = *a;
	*a = *b;
	*b = tmp;
}

void ListBubbleSort(ListNode **pListHead)
{
	assert(*pListHead);

	int iTotal = 0;
	ListNode *pSort_1 = (*pListHead);
	ListNode *pSort_2 = (*pListHead)->pNext;
	while (pSort_1){
		iTotal++;
		pSort_1 = pSort_1->pNext;
	}

	pSort_1 = (*pListHead);

	for (pSort_1 = (*pListHead); pSort_1->pNext != NULL; pSort_1 = pSort_1->pNext){
		for (pSort_2 = pSort_1->pNext; pSort_2 != NULL; pSort_2 = pSort_2->pNext){
			if (pSort_1->data > pSort_2->data){
				Swap(&pSort_1->data, &pSort_2->data);
			}
		}
	}
}

//查找单链表的中间节点,要求只能遍历一次链表 
void GetMid(ListNode *pListHead)
{
	if (pListHead == NULL){
		return;
	}
	ListNode *pSlow = pListHead;
	ListNode *pFast = pListHead;

	while (pFast->pNext->pNext){
		pSlow = pSlow->pNext;
		pFast = pFast->pNext->pNext;
	}
	printf("中间节点:%d  \n", pSlow->data);
}


//查找单链表的倒数第k个节点,要求只能遍历一次
DataType GetKTotail(ListNode *pListHead, int k)
{
	assert(pListHead);

	int i = 0;
	int total = 0;
	ListNode *pFind = pListHead;
	while (pFind){
		total++;
		pFind = pFind->pNext;
	}
	pFind = pListHead;

	for (i = k; i < total; ++i){
		pFind = pFind->pNext;
	}
	return pFind->data;
}

//删除链表的倒数第K个结点
//找到倒数第k+1个结点
void DelKthTotail(ListNode **pListHead, int k)
{
	assert(*pListHead);

	int i = 0;
	int total = 0;
	ListNode *pFind = *pListHead;
	ListNode *pDel = *pListHead;
	while (pFind){
		total++;
		pFind = pFind->pNext;
	}
	pFind = *pListHead;

	for (i = k + 1; i < total; ++i){
		pFind = pFind->pNext;
	}
	pDel = pFind->pNext;
	pFind->pNext = pDel->pNext;
	free(pDel);
}

int main()
{
	ListNode *SimpList;
	ListInit(&SimpList);

	InsertFront(&SimpList, 3);
	InsertFront(&SimpList, 4);
	InsertFront(&SimpList, 5);
	InsertFront(&SimpList, 6);
	InsertFront(&SimpList, 7);

	InsertBack(&SimpList, 98);
	InsertBack(&SimpList, 76);
	InsertBack(&SimpList, 54);
	InsertBack(&SimpList, 32);
	InsertBack(&SimpList, 10);

	FindKthTotail(SimpList, 6);	//查找第k个结点

	SimpListPrint(SimpList);

	DelFront(&SimpList);
	SimpListPrint(SimpList); 
	
	DelBack(&SimpList);
	SimpListPrint(SimpList);

	Reverse(&SimpList);
	SimpListPrint(SimpList);

	ListBubbleSort(&SimpList);
	SimpListPrint(SimpList);

	GetMid(SimpList);

	int k = 1;
	printf("倒数第%d个结点是:%d  \n", k, GetKTotail(SimpList, k));

	DelKthTotail(&SimpList, 5);
	SimpListPrint(SimpList);

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值