编程之美三——单链表

链表由一系列不必在内存中相连的结构组成,每一个结构均含有表元素和指向包含该元素后继元的结构指针。最后一个元素的后继指针指向NULL。

该结构(又称为结点)由两个域组成:数据域和指针域,数据域存储数据元素信息,指针域存储后继结点的地址。

链表的实现

typedef struct LNode  
{  
    ElemType data;  
    struct  LNode *next;  
}LNode, *LinkList;

面试题一:输入一个头结点,从尾到头反过来打印出每个结点的值

//可以用栈来实现,,每经过一个结点的时候,把该结点放到一个栈中
//遍历完整个链表的时候再从栈顶开始逐个输出结点的值
void printReverseList(LinkList phead)
{
	if(phead==NULL)
		return;
	stack<LinkList>nodes;
	LinkList pnode=phead;
	while(pnode!=NULL)
	{
		nodes.push(pnode);
		pnode=pnode->next;
	}
	while(!nodes.empty())
	{
		pnode=nodes.top();
		printf("%d\t",pnode->data);
		nodes.pop();
	}
}

面试题二:链表中倒数第K个结点

//设置两个指针,一前一后,先让前面那个指针移动K步
//然后连个指针同时移动,当前面那个指针移动到末尾的时候
//后面的指正正好指向倒数第K个结点
LinkList findKthNode(LinkList phead,int k)
{
	if(LinkList==NULL&&k==0)
		return NULL;
	LinkList pAhead=phead;
	LinkList pBehind=phead;
	if(int i=0;i<k-1;++i)
	{
		if(pAhead->next!=NULL)
			pAhead=pAhead->next;
		else
			return NULL;
	}
	while(pAhead->next!=NULL)
	{
		pAhead=pAhead->next;
		pBehind=pBehind->next;
	}
	return pBehind;
}

类似的还有求一个链表的中间结点,判断一个单向链表是否有环;

//找出链表的中间结点且当中间结点有两个时取第一个;
LinkList findMiddle(LinkList list)
{
	LinkList temp=list->next;
	if(NULL==temp)
		return NULL;
	LinkList pHead=list->next;
	while(pHead->next!=NULL&&pHead->next->next!=NULL)
	{
		pHead=pHead->next->next;
		temp=temp->next;
	}
	return temp;
}


面试题三:反转链表

LinkList reverseList(LinkList head)
{
	LinkList reversehead=NULL;
	LinkList node=head->next;
	LinkList pre=NULL;//保存当前结点的前一个结点;

	while(node!=NULL)
	{
		LinkList pNext = node->next;
		if(pNext==NULL)
			reversehead=node;
		node->next=pre;
		pre=node;
		node=pNext;

	}
	return reversehead;
}

面试题四:合并两个已经排序好的链表(递归实现)


LinkList mergeList(LinkList headA,LinkList headB)
{
	if(NULL==headA)
		return headB;
	
	if(NULL==headB)
		return headA;
	
	LinkList mergeHead=NULL;
	
	if(headA->data<headB->data)
	{
		mergeHead=headA;
		mergeHead->next = mergeList(headA->next,headB);

	}
	else
	{
		mergeHead=headB;
		mergeHead->next = mergeList(headA,headB->next);		
	}
	return mergeHead;
}

面试题五 约瑟夫环(循环链表)


在1,2......n的n个数字中每次删除第m个数字,求最后剩下的数字是多少

//每次删除第m个元素
int lastRemaining(int n,int m)
{
	LinkList list=creatCircle(n);
	LinkList node=list;

	LinkList p=list;
	
	while(node!=node->next)
	{
		for(int i=1;i<=m-2;i++)
		{
			node=node->next;
		}
		//删除第m个元素;
		LinkList deleteNode = node->next;
		node->next=deleteNode->next;
		free(deleteNode);
		node=node->next;
	}
	return node->data;
}

//创建约瑟夫环
LinkList creatCircle(int nNode)
{
	LinkList head,node;
	head = (LinkList)malloc(sizeof(LNode));
	node=head;
	for(int i=1;i<=nNode;i++)
	{
		LinkList temp = (LinkList)malloc(sizeof(LNode));
		temp->data=i;
		node->next=temp;
		node=temp;
	}
	node->next=head->next;//循环链表队尾指针指向头指针
	free(head);
	return node->next;
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值