在数据结构实验课上遇到这个问题,最开始的想法是用一个数组来存储数据,通过对数组长度取模的 方式来循环访问数组中的元素,但是问题是,已经出列元素的删除用普通数组不好实现(平白無故增加了o(n)的时间复杂度,于是就想到建立一个结构体(多加了一个bool,用来判断该元素是否已经出队);
/*用数组实现的难题是,元素的删除问题,某个元素出列以后,
*它仍然会占据数组空间;index取模访问元素时,可能会
*访问到已经出列的元素,考虑考虑用一个数组来存储已经出列的
*元素的下标,通过for循环来找到,下一个index,但是,问题是,
*太麻烦了,,时间复杂度也比较高*/是否可以用vector来实现?
*vector是否可以实现随机删除?
貌似是可以,,但是,还是比较麻烦,而且数组的删除还是会增加时间复杂度,即使这个操作已经被实现;要不,这个坑先留在这儿,有时间再填;
用数组不行,那很自然的就想到了循环链表;这里比较坑的是循环链表的删除问题,
1、删除首尾针所指的节点时要注意更新首尾指针的位置;
2、只剩一个节点(即head = head->next) 的时候,要特别处理;
而添加尾指针是为了插入方便,添加头指针是为了删除方便;如果只有尾指针,那么当删除的节点是尾指针所指节点时, 需要再遍历整个链表,找到尾指针的前驱节点,比较麻烦;
而普通的单链表一般是设立head节点,不需要考虑head删除以后,循环链表首尾断开的问题;
其删除操作如下:
https://blog.csdn.net/weixin_43484734/article/details/83302294
#include <iostream>
#include <vector>
using namespace std;
typedef struct Single{
int passwd;
int order;
bool leave;
Single* next;
}Single,*List ;
void Init(List& tail, List& head);/*List& tail,尾插法,设立尾指针,时间复杂度为o(1)*/
void Insert(List& tail,List& head, Single*& data);
void del(List& tail,List& head,List& work);//从尾节点开始查找,
void test01();
void test02();
void CountNum(Single* &passwd, int nodeNum, int m);
/*用环形链表实现比较方便一点*/
void CountNum2(List& tail, List& head,vector<int>& sout,int NodeNum, int m);
void Println(vector<int>& sout);
int main() {
test02();
return 0;
}
void test01() {
int a, n, m;
int nodeNum = 0;
cin>>a;
/*if(ab.leave == false){
cout<<"嗯,怎么不算呢?"<<endl;
};*/
Single *pwd = NULL;
for (int i = 0; i < a; ++i) {
cin>>n;
pwd = new Single[10];
for (int j = 0; j < n; ++j) {
cin>>pwd[i].passwd;
}
cin>>m;
nodeNum = n;
}
}
void test02() {
int a, n, m;
int nodeNum = 0;
vector<int> sout;
cin>>a;
List Head,tailor;
Init(tailor,Head);
for (int i = 0; i < a; ++i) {
cin>>n;
for (int j = 0; j < n; ++j) {
int temp = 0;
cin>>temp;
Single * data = new Single ;
data->passwd = temp;
data->order = j+1;
Insert(tailor,Head,data);
data = NULL;//避免出现野指针;
}
cin>>m;
CountNum2(tailor,Head,sout,n,m);
Println(sout);
// sout.swap(vector<int>());
if(i != a-1) {
cout<<endl;
}
}
}
void Insert( List& tail, List& head,Single*& data){
Single* temp = data ;
if(tail == NULL) {
head = tail = temp;
tail->next = head;
} else{
List back = tail->next;
tail->next = temp;
tail = tail->next;
tail->next = back;
head = back;
}
temp = NULL;
}
void Init(List& tail,List& head) {
tail = NULL; head = NULL;
}
void del(List& tail,List& head,List& work) {
bool del_flag = false;
List pre = tail;
List temp = head;
if(head != NULL) {
while (!del_flag) {
/*删除尾结点该如何解决
* 1、添加一个pre指针
* 2、那要是删的是pre指针,?*/
if (temp == temp->next) {/*只剩一个节点*/
/*temp = temp->next,我是sb,*/
delete temp;
temp = NULL;
head = NULL, tail = NULL;
del_flag = true;
} else if(work == temp) {
List del = temp;
pre->next = temp->next;
temp = temp->next;
if(work == head) {
head = temp;
}else if(work == tail) {
tail = pre;
}
delete del;
del_flag = true;
}else {
temp = temp->next;
pre = pre->next;
}
}
}
/*SIGSEGV (Segmentation fault) 出现这个错误的原因是,删除的时候
* 忽略了头尾指针,头尾指针不会移动;或者只需要尾指针?
* */
work = temp;
}
void CountNum(Single* &passwd, int nodeNum, int m) {
int index = 0, contrast = 0,count = 0;
int arrLength = nodeNum;
while(nodeNum != 0) {
if(m / nodeNum != 0) {
contrast = m % nodeNum;
}else{
contrast = m;
}
count++;
index++;
/*用数组实现的难题是,元素的删除问题,某个元素出列以后,
*它仍然会占据数组空间;index取模访问元素时,可能会
*访问到已经出列的元素,考虑考虑用一个数组来存储已经出列的
*元素的下标,通过for循环来找到,下一个index,但是,问题是,
*太麻烦了,,时间复杂度也比较高*/
if(count == contrast) {
}
}
}
void CountNum2(List& tail, List& head,vector<int>& sout,int NodeNum, int m) {
int index = 0, contrast = 0,count = 0;
List work = head;
while (NodeNum != 0) {/*work != NULL迭代条件不是这个;但是,如何判断循环链表是否为空呢*/
if(m % NodeNum == 0) {
contrast = NodeNum;
}else {
contrast = m % NodeNum;
}
count++;
if(count == contrast) {
sout.push_back(work->order);
m = work->passwd;
del(tail,head,work);
count = 0;
NodeNum--;
} else {
work = work->next;
}
}
/* if(work == NULL) {
cout<<"亲爱的旅人啊"<<endl;
}else {
cout<<"思维惰性"<<endl;
}*/
}
void Println(vector<int>& sout) {
/*2、输出结果*/
//cout<<sout.size()<<endl;
if(!sout.empty()) {
for (int i = 0; i < sout.size(); ++i) {
cout<<sout[i];
if(i != sout.size() - 1) {
cout<<" ";
}
}
}
sout.clear();
/*cout<<sout.size()<<endl;*/
}