文章目录
基础数据结构之链表的创建
0 - 链表
(1)存储类型不限,存储单元不连续
(2)操作:初始化,添加,遍历,插入,删除,查找,排序,释放等
(3)单向/双向,循环
(4)注意头结点位置不变(一般情况下都是的)
关于结构体指针:http://t.csdn.cn/mgBru
1. 动态单向链表:
- 临时分配链表节点 ---- 释放
- 创建过程:声明(node*) – 分配空间(new node) – 初始化(NULL)
//动态创建单向循环链表
#include<bits/stdc++.h>
using namespace std;
typedef struct node{
int data;
struct node* next;
};
int main()
{
int n = 10; // 结点数目
node* head=new node; head->data=1; head->next=NULL; // 为头结点分配空间,并初始化
node* pNew,*p; // pNew 是当前结点---用来添加结点,p是现在这个链表所指向的结点
p=head; //链表首先指向头部
p->next=NULL; //初始化结构体指针p----变量使用之前要初始化完
for(int i=2;i<=n;i++)
{
pNew=new node; //先分配空间
pNew->data=i; //后初始化
pNew->next=NULL;
p->next=pNew; //将pNew结点加入链表中
p=p->next; //p指向当前链表的最新结点
}
p->next = head; //末尾的下一个连接头部,构成循环链表
p=head; //指针回到头部
//测试一下
for(int i=0;i<n;i++)
{
cout<<p->data<<endl;
p=p->next;
}
return 0;
}
2. 静态链表:
- 空间大小已经提前分配好
- 对内存要求不严格,可以加快编码速度
2.1 单向
//创建单向静态循环链表
#include<bits/stdc++.h>
const int N=101;
struct node{
int id;
int nextid; //指向下一个结点的id
//int data; 如果有数据,根据实际情况添加
}Node[N];
int main()
{
int n=10;
for(int i=1;i<n;i++)
{
Node[i].id=i;
Node[i].nextid=i+1;
}
Node[n].id=n;
Node[n].nextid=1; //Node[10]=1 --- 尾端的结点指向头部,构成循环链表
int now=1;
for(int i=1;i<2*n;i++)
{
printf("%d ",Node[now].id);
now=Node[now].nextid;
}
}
2.2 双向
#include<bits/stdc++.h>
const int N=101;
struct node{
int id;
int nextid; //指向下一个结点的id
int previd; //指向前一个结点的id
}Node[N];
int main()
{
int n=10;
for(int i=1;i<n;i++)
{
Node[i].id=i;
Node[i].nextid=i+1;
Node[i].previd=i-1;
}
Node[1].previd=n; //头部结点的前一个结点为尾部结点
Node[n].id=n;
Node[n].previd=n-1;
Node[n].nextid=1; //Node[10]=1 --- 尾端的结点指向头部,构成循环链表
//测试一下
int now=1;
for(int i=1;i<2*n;i++)
{
printf("%d ",Node[now].id);
now=Node[now].nextid;
}
return 0;
}
2.3 用一位数组实现单向静态链表
//一位数组实现单向静态循环链表
#include<bits/stdc++.h>
const int N=101;
int Nodes[N];
int main()
{
int n=10;
for(int i=1;i<n;i++)
{
Nodes[i]=i+1; //结点的数据表示的是下一个结点的索引
}
Nodes[n]=1; //结尾指向头部,构成循环链表
//测试一下
int now=1;
for(int i=1;i<2*n;i++)
{
printf("%d ",Nodes[now]);
now=Nodes[now];
}
return 0;
}
约瑟夫问题
题目描述
n n n 个人围成一圈,从第一个人开始报数,数到 m m m 的人出列,再由下一个人重新从 1 1 1 开始报数,数到 m m m 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。
注意:本题和《深入浅出-基础篇》上例题的表述稍有不同。书上表述是给出淘汰 n − 1 n-1 n−1 名小朋友,而该题是全部出圈。
输入格式
输入两个整数 n , m n,m n,m。
输出格式
输出一行 n n n 个整数,按顺序输出每个出圈人的编号。
样例 #1
样例输入 #1
10 3
样例输出 #1
3 6 9 2 7 1 8 5 10 4
提示
1 ≤ m , n ≤ 100 1 \le m, n \le 100 1≤m,n≤100
动态创建链表
//替换掉测试部分即可
while((n--)>=1)
{
for(int i=1;i<m;i++)
{
prev=now; //用prev记录前一个指针
now=now->next;
}
printf("%d ",now->data);
prev->next=now->next;
now=prev->next;
}
静态数组创建单向循环列表
//替换掉测试部分即可
int prev=1,now=1;
while((n--)>=1)
{
for(int i=1;i<m;i++) //数了两下
{
prev=Node[now].id;
now=Node[now].nextid;
}
//第三下开始踢人i
printf("%d ",now);
now=Node[now].nextid; //now指向i的下一个结点
Node[prev].nextid=now; //前一个结点的下一个指向i的下一个
}
return 0;
一位数组创建单向循环链表
//替换掉测试部分即可
int now=1,prev=1;
while((n--)>=1)
{
for(int i=1;i<m;i++)
{
prev=now;
now=arr[now];
}
printf("%d ",now);
arr[prev]=arr[now];
now=arr[prev];
}
return 0;