C++ - 在不使用节点构造函数的情况下插入链表。可能吗?
C++ - Insertion in a Linked List without using a node's constructor. Is it possible?
我正致力于在 C++ 中实现一个模板化链表,该链表将用于模拟火车穿过许多停靠站,其中添加和删除了火车车厢。 Traincar 是它自己的 class,每个对象都应该被赋予一个从 1 开始的唯一 ID,并在添加汽车时递增。但是,当 运行 我的代码时,id 的增量超出了预期。
经过一些实验并在先前答案的帮助下,我确定是 LinkedList
class 方法中的 new node
语句导致 id 增加得更多比想要的。但是,我没有看到在不创建 new node
的情况下实现 insertion
方法的方法。有什么解决办法吗?
这是我的 TrainCar
class:
class TrainCar {
public:
static int nextID;
int id;
char typeOfCar;
int numberOfStops;
node<char>* car;
TrainCar();
};
int TrainCar::nextID = 1;
TrainCar::TrainCar() {
cout << "id++" << endl;
id = nextID++;
int i = (rand() % 3);//gives a random number 0 - 2, used to determine what
//type of car to add
if(i == 0) {
typeOfCar = 'P';
}
else if(i == 1) {
typeOfCar = 'C';
}
else {
typeOfCar = 'M';
}
car = new node<char>(typeOfCar);
numberOfStops = (rand() % 5) + 1;//gives a random number 1 - 5;
}
这是我的 main()
函数
int main() {
LinkedList<TrainCar> train;
int addCargoCar = 0;
for(int i = 0; i < 10; i++) {
TrainCar newCar;
if(newCar.typeOfCar == 'P') {
train.AddToFront(newCar);
addCargoCar++;
}
else if(newCar.typeOfCar == 'C') {
train.AddAtIndex(newCar, addCargoCar);
}
else {
train.AddToEnd(newCar);
}
}
cout <<"Welcome to the Train Station! Here is your train!" << endl;
char type;
int id, numberOfStops, i, j;
for(i = 0; i < train.size; i++) {
type = train.Retrieve(i).typeOfCar;
id = train.Retrieve(i).id;
numberOfStops = train.Retrieve(i).numberOfStops;
cout << "[" << id << ":" << type << ":" << numberOfStops << "] ";
}
}
输出应该类似于
[5:P:1][6:P:4][8:P:2][3:P:2][10:C:3][2:C:3][4:C:1][1:M:1][7:M:3][9:M:2]
但我的输出是:
[17:P:2][9:P:2][5:C:2][19:C:1][15:C:2][1:M:5][3:M:4][7:M:1][11:M:3][13:M:1]
编辑:这是 AddToFront()
方法:(所有其他添加方法在本质上都是相似的)。输出的问题是 new node<T>(d)
语句
template <class T>
void LinkedList<T>::AddToFront(T d) {
node<T>* newNode = new node<T>(d);
if(head == NULL) {
head = newNode;
tail = newNode;
size++;
}
else {
newNode->next = head;
head = newNode;
size++;
}
}
Edit2:这是我的检索函数(现已修复,不再使用 new node
语句):
template <class T>
T LinkedList<T>::Retrieve(int index) {
node<T>* cur = head;
for(int i = 0; i < index; i++) {
cur = cur->next;
}
return(cur->data);
}
您使用 static
成员变量来跟踪标识符的想法是正确的。 但是你不能只那个。
static
成员变量是 class 的成员,而不是任何特定对象。因此所有对象共享相同的 id
.
使用一个静态成员来跟踪下一个可能的id,然后使用一个non-static成员变量来存储对象的实际 ID。
类似
class TrainCar {
public:
static int next_id; // Used to get the id for the next object
int id; // The objects own id
...
};
TrainCar::TrainCar() {
id = next_id++; // Get next id and save it
...
}
您可能还应该有一个复制构造函数和复制赋值运算符,否则您可能会得到两个具有相同 ID 的对象。
关于
Why are the id values so high and why are they being incremented by more than one each time?
那是因为您创建的对象可能比您预期的要多。使用您显示的代码以及上面建议的更改,您将为每个默认构造的对象创建一个新的 id。根据您的 LinkedList
模板 class 正在做什么(您为什么不使用 std::vector
),可能会创建新对象。
一个有根据的猜测是你的列表 class 的 Retreive
函数默认构造它包含的对象。这就是为什么你在打印时得到三个对象的原因,因为你调用 Retrieve
三次。可能与您的 Add
函数有类似的故事。
我正致力于在 C++ 中实现一个模板化链表,该链表将用于模拟火车穿过许多停靠站,其中添加和删除了火车车厢。 Traincar 是它自己的 class,每个对象都应该被赋予一个从 1 开始的唯一 ID,并在添加汽车时递增。但是,当 运行 我的代码时,id 的增量超出了预期。
经过一些实验并在先前答案的帮助下,我确定是 LinkedList
class 方法中的 new node
语句导致 id 增加得更多比想要的。但是,我没有看到在不创建 new node
的情况下实现 insertion
方法的方法。有什么解决办法吗?
这是我的 TrainCar
class:
class TrainCar {
public:
static int nextID;
int id;
char typeOfCar;
int numberOfStops;
node<char>* car;
TrainCar();
};
int TrainCar::nextID = 1;
TrainCar::TrainCar() {
cout << "id++" << endl;
id = nextID++;
int i = (rand() % 3);//gives a random number 0 - 2, used to determine what
//type of car to add
if(i == 0) {
typeOfCar = 'P';
}
else if(i == 1) {
typeOfCar = 'C';
}
else {
typeOfCar = 'M';
}
car = new node<char>(typeOfCar);
numberOfStops = (rand() % 5) + 1;//gives a random number 1 - 5;
}
这是我的 main()
函数
int main() {
LinkedList<TrainCar> train;
int addCargoCar = 0;
for(int i = 0; i < 10; i++) {
TrainCar newCar;
if(newCar.typeOfCar == 'P') {
train.AddToFront(newCar);
addCargoCar++;
}
else if(newCar.typeOfCar == 'C') {
train.AddAtIndex(newCar, addCargoCar);
}
else {
train.AddToEnd(newCar);
}
}
cout <<"Welcome to the Train Station! Here is your train!" << endl;
char type;
int id, numberOfStops, i, j;
for(i = 0; i < train.size; i++) {
type = train.Retrieve(i).typeOfCar;
id = train.Retrieve(i).id;
numberOfStops = train.Retrieve(i).numberOfStops;
cout << "[" << id << ":" << type << ":" << numberOfStops << "] ";
}
}
输出应该类似于
[5:P:1][6:P:4][8:P:2][3:P:2][10:C:3][2:C:3][4:C:1][1:M:1][7:M:3][9:M:2]
但我的输出是:
[17:P:2][9:P:2][5:C:2][19:C:1][15:C:2][1:M:5][3:M:4][7:M:1][11:M:3][13:M:1]
编辑:这是 AddToFront()
方法:(所有其他添加方法在本质上都是相似的)。输出的问题是 new node<T>(d)
语句
template <class T>
void LinkedList<T>::AddToFront(T d) {
node<T>* newNode = new node<T>(d);
if(head == NULL) {
head = newNode;
tail = newNode;
size++;
}
else {
newNode->next = head;
head = newNode;
size++;
}
}
Edit2:这是我的检索函数(现已修复,不再使用 new node
语句):
template <class T>
T LinkedList<T>::Retrieve(int index) {
node<T>* cur = head;
for(int i = 0; i < index; i++) {
cur = cur->next;
}
return(cur->data);
}
您使用 static
成员变量来跟踪标识符的想法是正确的。 但是你不能只那个。
static
成员变量是 class 的成员,而不是任何特定对象。因此所有对象共享相同的 id
.
使用一个静态成员来跟踪下一个可能的id,然后使用一个non-static成员变量来存储对象的实际 ID。
类似
class TrainCar {
public:
static int next_id; // Used to get the id for the next object
int id; // The objects own id
...
};
TrainCar::TrainCar() {
id = next_id++; // Get next id and save it
...
}
您可能还应该有一个复制构造函数和复制赋值运算符,否则您可能会得到两个具有相同 ID 的对象。
关于
Why are the id values so high and why are they being incremented by more than one each time?
那是因为您创建的对象可能比您预期的要多。使用您显示的代码以及上面建议的更改,您将为每个默认构造的对象创建一个新的 id。根据您的 LinkedList
模板 class 正在做什么(您为什么不使用 std::vector
),可能会创建新对象。
一个有根据的猜测是你的列表 class 的 Retreive
函数默认构造它包含的对象。这就是为什么你在打印时得到三个对象的原因,因为你调用 Retrieve
三次。可能与您的 Add
函数有类似的故事。