您的位置:首页 > 理论基础 > 数据结构算法

数据结构之循环链表

2016-04-19 22:19 330 查看
      单链表是十分常用的一种数据结构了,而关于单链表的相关面试题也是层出不穷。经典的问题就是约瑟夫环问题,就可以采用单链表进行解决。

      约瑟夫环的问题描述如下:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。与此类似,猴子选大王等等。

      一般解决这类问题,常见的方法就是递归和循环链表。递归的方法简单,但是时间复杂度高。而采用循环链表,则能够降低时间复杂度。

    循环链表是指单链表的末尾指针指向了第一个结点的这样一种单链表。(注意不是头节点,因为头节点上时不存储数据的。)所以,我们可以根据情况,将头节点进行删除。

   循环链表判断是否为空链表的条件也和单链表有所不同。它的判断条件时第一个数据节点的下一个元素指向的是第一个元素自身。

   下面就给出循环链表的示例代码:

#include <iostream>
using namespace std;
struct Node{
int data;
Node* pNext;// 节点指针
};
typedef Node* LinkList;
// 头插法创建单链表
LinkList LinkedListCreatH(int m)
{
Node *head;
head = (Node *)malloc(sizeof(Node)); //申请头结点空间
head->pNext = NULL; //初始化一个空链表
head->data = 0;
Node* temp = head;

Node *p;
for (int i = 1;i <= m; i++) {
p = (Node*)malloc(sizeof(Node));
p->data = i;
temp->pNext = p;
temp = temp->pNext;
}
temp->pNext = head->pNext;// 将指针指向头节点,形成循环链表
// 删除头节点
Node* delNode = head;
head = head->pNext;
free(delNode);
return head;
}
// 解决约瑟夫环的问题,从编号为K的元素开始,每逢m则出列
void print_link(LinkList L,int k,int m){
Node* ptemp = L;
Node* delNode = NULL;
for (int i = 0; i < k; i++) {
ptemp = ptemp->pNext;
}
cout<<"输出约瑟夫环的结果 :"<<endl;
while (ptemp->pNext != ptemp) {// 进行循环输出
for (int i = 0;i < m-1; i++) {
ptemp = ptemp->pNext;
}
delNode = ptemp->pNext;//临时指针指向需要删除的元素
cout<<delNode->data<<endl;
ptemp->pNext = ptemp->pNext->pNext;//修改指针指向,跳过需要删除的元素
free(delNode);// 删除节点
}
cout<<ptemp->data<<endl;
free(ptemp);
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
LinkList L = LinkedListCreatH(5);
print_link(L,3,3);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: