Error: Debug Assertion Failed!
It took a long time to resolve an error in this article today. A code bug is inevitable, but we can optimize and reduce it as much as possible.
Error Analysis: The main reason is that the template class of the circular single-chain list in my previous article was used to solve the problem of Joseph rings, but I did not use the Remove member function in the template class (not because of the limitations of the delete function I defined), but rather
preNode = currNode;
currNode =currNode->link;
The problem is that the last private member (i.e., the pointer always pointing to the end of a circular single-chain list) is not updated at this time, that is, the last pointer to the node has already been delete d, and when the main function returns, the destructor is called by the systemThe last-pointed node will be released again and errors will occur in the diagram.(This is my analysis result for more than an hour. If something is wrong, I hope Daniel will correct it!).Paste the code below for the error:
Okay, now paste the whole Joseph problem (including the template classes and the main functions of the circular single-chain list). Joseph rings are an important application of circular single-chain list, and also a very practical problem. I hope everyone can master it. If not, I hope you can make corrections and criticisms!
//Template class
//Circular Chain List Template class
#include <iostream>
using namespace std;
template<class T>
struct CircleLinkNode {
T data;
CircleLinkNode<T> *link;
//Constructor
CircleLinkNode(CircleLinkNode<T> * next = NULL) : link(next) {}
CircleLinkNode(T d, CircleLinkNode<T> * next = NULL) : data(d), link(next) {}
};
template<class T>
class CircleList {
public:
CircleList(const T & x); //Constructor
CircleList(CircleList<T> & L); //copy constructor
~CircleList(); //Destructor
int Length() const; //Calculating the Length of a Circular Chain List
bool IsEmpty()
{
return first->link == first ? true : false; //Determine if it is an empty table?
}
CircleLinkNode<T> * getHead() const; //Returns the address of the additional header node
void setHead(CircleLinkNode<T> * p); //Set the address of the additional header node
CircleLinkNode<T> * Search(T x); //Search for nodes with data x
CircleLinkNode<T> * Locate(int i); //Search for the address of the f i rst element
T getData(int i); //Remove the value of the f i rst element
void setData(int i, T & x); //Modify the value of the first element with
bool Insert(int i, T & x); //Insert x after the f i rst element
bool Remove(int i, T & x); //Delete the ith element and save the deleted data with x
void createList(T endFlag); //Create a single-linked list
void outputList(int stopSequence);
protected:
CircleLinkNode<T> *first, *last; //Head pointer, tail pointer
};
//Function Definition
template<class T>
CircleList<T>::CircleList(const T & x) {
//Constructor: Open up the header nodes and assign values
first = new CircleLinkNode<T>(x);
first->link = first;
last = first;
}
template<class T>
CircleList<T>::~CircleList() {
//Release corresponding resources
//if (last != first) {
// delete last;
//}
delete first;
}
template<class T>
CircleLinkNode<T> * CircleList<T>::getHead() const {
//Get the function's header pointer
return first;
}
template<class T>
int CircleList<T>::Length() const {
//Calculating the length of a chain table
CircleLinkNode<T> *calculLen = NULL;
int Len = 0;
calculLen = first->link;
while (calculLen != first) { //Returns the length of the count when loop to first again
Len++;
calculLen = calculLen->link;
}
return Len;
}
template<class T>
CircleList<T>::CircleList(CircleList<T> &L) {
//copy constructor
int Len = Length(); //Get the length of the current list
CircleLinkNode<T> *create = NULL, *destData, *srcData;
create = new CircleLinkNode<T>(0);
if (!create) {
cerr << "memory alloc error" << endl;
exit(1);
}
last = create; //Tag tail node
for (int i = 0; i < Len - 1; i ++) {
create->link = first->link;
first->link = create;
create = new CircleLinkNode<T>(0);
if (!create) {
cerr << "memory alloc error" << endl;
exit(1);
}
}
//copy data fields from L to the current list one by one
copyData = first->link;
srcData = L.first->link;
while (srcData == L.first) {
destData->data = srcData->data;
destData = destData->link;
srcData = srcData->link;
}
//Building a circular chain table
last->link = first;
}
template<class T>
CircleLinkNode<T> * CircleList<T>::Search(T x) {
//Find a node whose data field is x and return its address
CircleLinkNode<T> * current = NULL;
current = first->link;
while (current != first) {
if (current->data == x) {
break;
}
current = current->link;
}
return current;
}
template<class T>
CircleLinkNode<T> * CircleList<T>::Locate(int i) {
//Location function that returns the address of the ith node for insertion and deletion functions
if (i < 0 || i > Length()) {
cout << "Illegal data" << endl;
cin >> i;
return NULL;
}
CircleLinkNode<T> * current = NULL;
current = first;
for (int j = 0; j < i; j ++) {
current = current->link;
}
return current;
}
template<class T>
void CircleList<T>::createList(T endFlag) {
//Create single-chain list in reverse order
T inputData = 0;
CircleLinkNode<T> *create = NULL;
cin >> inputData;
create = new CircleLinkNode<T>(inputData); //Create a tail node outside the loop
if (!create) {
cerr << "memory alloc error" << endl;
exit(1);
}
last = create; //Tag tail node
while (inputData != endFlag) { //Whether the end condition is met
create->link = first->link; //Establish links
first->link = create;
cin >> inputData;
create = new CircleLinkNode<T>(inputData); //Build other nodes in turn
if (!create) {
cerr << "memory alloc error" << endl;
exit(1);
}
}
//Single Chain List Establishment Completed
last->link = first; //Building a circular chain table
}
template<class T>
T CircleList<T>::getData(int i) {
CircleLinkNode<T> * current;
current = Locate(i); //Locate function calls
return current->data;
}
template<class T>
void CircleList<T>::setData(int i, T & x) {
//Set the data field of the ith node to x
CircleLinkNode<T> * current = NULL;
current = Locate(i);
current->data = x; //Complete Modification
}
template<class T>
bool CircleList<T>::Insert(int i, T & x) {
//Insert a new node after the first node and assign its data field to x
CircleLinkNode<T> * flagPtr;
CircleLinkNode<T> * newNode = new CircleLinkNode<T>(x);
if (!newNode) { //memory alloc error
return false;
}
if (0 == i) { //Insert at the top
newNode->link = first->link;
first->link = newNode;
}
else {
flagPtr = Locate(i);
newNode->link = flagPtr->link;
flagPtr->link = newNode;
}
//Update last-pointed node
last = Locate(Length());
return true;
}
template<class T>
bool CircleList<T>::Remove(int i, T & x) {
//Delete the ith node and store the deleted data in x
CircleLinkNode<T> *preNode = NULL, *delNode = NULL;
preNode = Locate(i - 1);
delNode = Locate(i);
preNode->link = delNode->link;
delete delNode;
return true;
}
template<class T>
void CircleList<T>::outputList(int stopSequence) {
if (first == first->link) {
cout << "This is an empty table" << endl;
return;
}
//Output loop list until specified sequence number stops output (easy to test loop characteristics)
CircleLinkNode<T> * current = NULL;
current = first->link;
for (int i = 0; i < stopSequence; i ++) {
cout << current->data << " ";
current = current->link;
if (current == first) {
current = current->link; //Skip first output
}
}
cout << endl;
}
Main Function and Joseph Processing Function Test
//An example of a circular chain table to solve the Joseph problem
#include <iostream>
#include "CircleList.cpp"
using namespace std;
template<class T>
void Josephus(CircleList<T> & js, int n, int m);
int main()
{
CircleList<int> circle(0);
int nodesAmount = 0, delSequence = 0, data = 0, sotre;
cout << "Enter the number of players and the number of reports interval:" << endl;
cin >> nodesAmount >> delSequence;
for (int i = 0; i < nodesAmount; i ++) { //Form Joseph rings
data = i + 1;
circle.Insert(i, data);
}
Josephus(circle, nodesAmount, delSequence); //Solve the Joseph problem
system("pause");
return 0;
}
template<class T>
void Josephus(CircleList<T> & js, int n, int m) {
//To solve the Joseph problem
//Parameters: Circular Chain List, Number of Nodes, Delete Interval of Nodes
CircleLinkNode<T> *preNode = NULL, *currNode = NULL; //Define two flag nodes
preNode = js.getHead();
currNode = preNode->link;
for (int i = 0; i < n - 1; i ++) { //Loop n - once, with only one node left
for (int j = 0; j < m - 1; j ++) { //One report cycle at a time
if (currNode == js.getHead()) {
preNode = currNode;
currNode = currNode->link;
}
//Start deleting node after message count
preNode = currNode;
currNode = currNode->link;
if(currNode == js.getHead()) {
preNode = currNode;
currNode = currNode->link;
}
}
cout << "The data deleted is: " << currNode->data << endl;
preNode->link = currNode->link;
delete currNode;
currNode = preNode->link; //Don't miss this step
}
}
The results of normal operation show that:
Data structure needs a lot of time to practice and research, I hope we can spend more time to practice, cherish the current time, and do anything with a goal!