数据结构之循环链表
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;
}
约瑟夫环的问题描述如下:已知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;
}
相关文章推荐
- 啊哈!算法【转】
- 菜鸟nginx源代码剖析数据结构篇(八) 缓冲区链表ngx_chain_t
- 数据结构--二叉树的遍历
- 数据结构算法应用C++语言描述——(1)C++基础知识
- MySQL索引背后的数据结构及算法原理
- (转载)动态规划之背包问题(一)
- 【数据结构】二叉树的实现(如:默认成员函数、(叶子)节点数、深度、四种遍历)
- 数据结构学习安排
- 数据结构串之块链串
- 数据结构串之堆串
- 数据结构之串——顺序串
- 数据结构和算法16 之堆排序
- 数据结构和算法15 之二叉树排序
- 关于在牛客网上做题的解析之数据结构(每日20道题,记录错误和不懂的题)
- 广义表(非线性结构)
- 数据结构概念解析之—空间复杂度
- 数据结构和算法14 之归并排序
- 数据结构概念解析之—时间复杂度
- 【数据结构】ArrayList原理及实现学习总结
- HashTable与多条件筛选