Не работает вставка элемента в линейный двусвязный (двунаправленный) список
Задача в следующем - реализовать линейный двусвязный список, также программа должна добавлять, удалять, выводить элементы списка. Все работает, кроме вставки элемента в указанное место (в конец и в начало списка вставляется).
Сам код:
#include <iostream>
#include <cmath>
using namespace std;
struct Element {
Element *prev, *next;
int data;
};
Element *createElement(int data, Element *prev, Element *next);
Element *insFirst(Element *head, int data);
Element *insLast(Element *head, int data);
Element *insElement(Element *head, Element *current, int data);
Element *insElement(Element *head, int position, int data);
Element *delElement(Element *head, Element *current);
Element *delElement(Element *head, int position);
Element *findElement(Element *head, Element *current, int data);
Element *menu(Element *head);
Element *delete2b2m(Element *head);
void scanList(Element *head);
void deleteList(Element *head);
void randList(Element *head);
int correctInput(const char str[]);
int lenList = 0;
int main() {
Element *headEl = createElement(0, NULL, NULL);
while (headEl != NULL){
headEl = menu(headEl);
}
return 0;
}
Element *createElement(int data, Element *prev = NULL, Element *next = NULL){
Element *newElement = new Element;
newElement->data = data;
newElement->next = next;
newElement->prev = prev;
return newElement;
}
void deleteList(Element *head){
Element *current = head;
Element *next = NULL;
while (current != NULL){
next = current->next;
delete current;
current = next;
}
}
Element *insFirst(Element *head, int data){
Element *additionEl = createElement(data, NULL, NULL);
if (head == NULL){
lenList++;
return additionEl;
}
else if (lenList == 0){
head->data = data;
lenList++;
return head;
}
else {
additionEl->next = head;
head->prev = additionEl;
lenList++;
}
return additionEl;
}
Element *insLast(Element *head, int data){
Element *additionEl = createElement(data, NULL, NULL);
Element *current = head;
if (head == NULL){
lenList++;
return additionEl;
}
else if (lenList == 0){
head->data = data;
lenList++;
return head;
}
else {
int i = 0;
while (current->next != NULL){
current = current->next;
i++;
}
additionEl->prev = current;
current->next = additionEl;
lenList++;
return head;
}
}
Element *insElement(Element *head, int position, int data){
Element *additionEl = createElement(data, NULL, NULL);
Element *current = head;
if (head == NULL){
lenList++;
return additionEl;
}
else if (lenList == 0){
head->data = data;
lenList++;
return head;
}
else if (position >= 0 ){
int i = 0;
while (i < position){
if (current != NULL) {
current = current->next;
i++;
}
else break;
}
if ((current == NULL) && (i < position)) {
cout << "Слишком большой индекс, вставляем в конец. " << endl;
}
additionEl->prev = current->prev;
current->prev = additionEl;
additionEl->next = current;
lenList++;
return head;
}
else {
return NULL;
}
}
Element *insElement(Element *head, Element *current, int data){
Element *additionEl = createElement(data, NULL, NULL);
if (head == NULL){
return additionEl;
}
else {
if (current->next != NULL) {
current->next->prev = additionEl;
}
additionEl->next = current->next;
current->next = additionEl;
additionEl->prev = current;
lenList++;
return head;
}
}
Element *delElement(Element *head, Element *current){
if (current != NULL) { // Проверка входных данных
if (current == head) {
if (head->next == NULL){
lenList = 0;
delete head;
head = createElement(-1, NULL, NULL);
}
else{
head = head->next;
delete current;
head->prev = NULL;
lenList--;
}
return head;
}
else {
if (current->next == NULL){ // если элемент последний
current->prev->next = NULL;
delete current;
lenList--;
return head;
}
else {
Element *additionEl;
additionEl = current->next;
additionEl->prev = current->prev;
current->prev->next = additionEl;
delete current;
lenList--;
return head;
}
}
}
else
return NULL;
}
Element *delElement(Element *head, int position){
Element *current = head;
if (position >= 0) { // Проверка входных данных
if (position == 0) {
if (head->next == NULL){
lenList = 0;
delete head;
head = createElement(-1, NULL, NULL);
}
else{
head = head->next;
delete head->prev;
head->prev = NULL;
lenList--;
}
return head;
}
else {
int i = 0;
while ((i != position) && (current->next != NULL)){
current = current->next;
i++;
}
if ((current->next == NULL) && (i < position)){
cout << "Слишком большой индекс, удаляю последний эелемент. " << endl;
current->prev->next = NULL;
delete current;
lenList--;
return head;
}
else {
Element *additionEl;
additionEl = current->next;
additionEl->prev = current->prev;
current->prev->next = additionEl;
delete current;
lenList--;
return head;
}
}
}
else
return NULL;
}
void scanList(Element *head){
Element *additionEl;
additionEl = head;
int i = 0;
while (additionEl != NULL) {
cout << "[" << i << "] " << additionEl->data << endl;
i++;
additionEl = additionEl->next;
}
lenList = i;
}
Element *findElement(Element *head, Element *current, int data){
Element *additionEl;
if (head) {
additionEl = head;
while ((additionEl != NULL) && (additionEl->data != data)) {
additionEl = additionEl->next;
}
current = additionEl;
}
else {
current = NULL;
}
return current;
}
Element *menu(Element *head){
cout << "\n" << endl;
cout << "1. Добавить элемент " << endl;
cout << "2. Удалить элемент " << endl;
cout << "3. Заполнить список случайными числами " << endl;
cout << "4. Вывести список " << endl;
cout << "5. Удалить два наименьших и два наибольших элемента " << endl;
cout << "6. Выход " << endl;
int choise = correctInput("\nTURN: ");
switch (choise)
{
case 1:
if ((head == NULL) || (lenList == 0)){
cout << "Список пуст." << endl;
int data = correctInput("Введите значение первого элемента: ");
head = createElement(data, NULL, NULL);
lenList++;
}
else {
cout << "Список непуст." << endl;
scanList(head);
cout << "[-1] " << "вставить в конец " << endl;
int position = correctInput("\nВ какое место вставить элемен: ");
int data = correctInput("Введите значение элемента: ");
if (position == 0){
head = insFirst(head, data);
}
else if (position > 0){
head = insElement(head, position, data);
// cout << " " << head << endl;
}
else {
head = insLast(head, data);
}
cout << "Готово!" << endl;
scanList(head);
}
return head;
case 2:
if ((head == NULL) || (lenList == 0)){
cout << "Список пуст, удалять нечего. " << endl;
}
else {
scanList(head);
int position = correctInput("\nВведите индекс удаляемого элемента: ");
if (position >= 0){
head = delElement(head, position);
}
else {
cout << "Неизвестный индекс. " << endl;
}
}
return head;
case 3:
cout << "Очищщаем предыдущий список. " << endl;
deleteList(head);
head = createElement((rand() % 1000 + 1), NULL, NULL);
randList(head);
return head;
case 4:
if (lenList == 0){
cout << " - Список пуст - " << endl;
}
else {
scanList(head);
}
return head;
case 5:
if (lenList >= 4) {
head = delete2b2m(head);
cout << "Результат: " << endl;
scanList(head);
}
else {
cout << "Элементов должно быть не меньше 4 " << endl;
}
return head;
case 6:
deleteList(head);
return NULL;
case 7:
cout << "lenlist = " << lenList << endl;
return head;
default:
cout << "Неизвестный пункт " << endl;
return head;
}
return NULL;
}
void randList(Element *head){
int count = correctInput("Введите количество элементов: ");
int randomdata;
if (count >= 4) {
for (int i = 0; i < count; i++){
randomdata = (rand() % 1000 + 1);
head = insLast(head, randomdata);
}
cout << "Список из " << count << " элементов создан: " << endl;
scanList(head);
}
else {
cout << "Список не создан. Элементов должно быть не меньше 4 " << endl;
}
}
Element *delete2b2m(Element *head){
for (int i = 0; i < 2; i++){
Element *maxEl = head;
Element *minEl = head;
Element *current = head;
while (current != NULL) {
if (current->data > maxEl->data){
maxEl = current;
}
if (current->data < minEl->data){
minEl = current;
}
current = current->next;
}
head = delElement(head, maxEl);
head = delElement(head, minEl);
}
return head;
}
int correctInput(const char str[]){
int x;
cout << str;
cin >> x;
while (cin.fail() || (cin.get() != '\n')){
cin.clear(); //сброс флага ошибки cin.fail;
cin.ignore(numeric_limits<streamsize>::max(),'\n'); //очистка потока от оставшихся символов
cerr << "Введено некорректное значение!" << endl;
cout << str;
cin >> x;
}
return x;
}
Функция insElement() должна добавлять элемент в указанное место. Либо по индексу, либо рядом с передаваемым элементом, но она не работает. Однако функции insFirst() и insLast() работают исправно.
При отладке обнаружил, что на этапе
additionEl->prev = current->prev;
current->prev = additionEl;
additionEl->next = current;
lenList++;
в функции insElement() addition и current связывают друг друга и своих соседей правильно, однако если идти от head->next->next->.. до нужного элемента, то никаких изменений нет, элемент не вставляется, и при выводе списка соответственно тоже никаких изменений.
Ответы (1 шт):
Разобрался.
В комментах дали пару советов, переписал все учитывая их, и все заработало.
Переписал все функции как методы структур и сделал отдельную структуру, которая отвечает за список целиком (хранит указатель на начало списка и длину всего списка).
Помимо того, что все заработало, еще и код сократился на 150 строк)
#include <iostream>
#include <cmath>
using namespace std;
int correctInput(const char str[]);
struct Element{
int data;
Element *prev;
Element *next;
Element *create(int data, Element *prev = NULL, Element *next = NULL){
Element *newElement = new Element;
newElement->data = data;
newElement->next = next;
newElement->prev = prev;
return newElement;
}
};
struct List{
Element *head;
int lenList;
List(Element *head = NULL, int lenList = 0){
this->head = head;
this->lenList = lenList;
}
void insert(int position, int data){
if (position == 0){
Element *add = add->create(data, NULL, NULL);
if (head == NULL){
head = add;
lenList++;
}
else {
head->prev = add;
add->next = head;
head = add;
lenList++;
}
}
else if ((position > 0) && (position <= lenList)){
Element *current = head;
if (position == lenList){
for (int i=0; i < position-1; i++){
current = current->next;
}
Element *add = add->create(data, current, NULL);
current->next = add;
lenList++;
}
else {
for (int i=0; i < position; i++){
current = current->next;
}
insert(current, data);
}
}
else {
cout << "Недопустимый индекс. " << endl;
}
}
void insert(Element *current, int data){
Element *add = add->create(data);
if (current != NULL){
add->next = current;
add->prev = current->prev;
add->prev->next = add;
current->prev = add;
lenList++;
}
}
Element *find(int data){
Element *current = head;
while (current != NULL){
if (current->data == data)
break;
current = current->next;
}
return current;
}
void show(){
Element *current = head;
int i = 0;
while (current != NULL){
cout << "[" << i << "] " << current->data << endl;
i++;
current = current->next;
}
}
void del(Element *del){
if (del != NULL) {
if (del == head){
head = head->next;
head->prev = NULL;
delete del;
lenList--;
}
else if (del->next == NULL){
del->prev->next = NULL;
delete del;
lenList--;
}
else {
del->next->prev = del->prev;
del->prev->next = del->next;
delete del;
lenList--;
}
}
}
void del(int position){
if ((position < lenList) && (position >= 0)){
Element *current = head;
for (int i=0; i < position; i++)
current = current->next;
del(current);
}
else
cout << "Недопустимый индекс. " << endl;
}
void clear(){
Element *current = head;
Element *next = NULL;
while (current != NULL){
next = current->next;
delete current;
current = next;
}
}
void random(int len){
int randomdata;
for (int i=0; i < len; i++){
randomdata = (rand() % 1000 + 1); // значения от 0 до 1000
insert(lenList, randomdata);
}
}
void delete2b2m(){
if (lenList < 4)
cout << "В списке слишком мало элементов. " << endl;
else{
for (int i=0; i < 2; i++){
Element *current = head;
Element *minEl = head;
Element *maxEl = head;
while (current != NULL){
if (current->data > maxEl->data)
maxEl = current;
if (current->data < minEl->data)
minEl = current;
current = current->next;
}
if (minEl == maxEl) // Если мин и макс элементы равны, значит весь список из равных элементов
minEl = minEl->next;
del(maxEl);
del(minEl);
}
}
}
};
int main(){
List list_1;
int flag = 1;
while (flag){
cout << "\n" << endl;
cout << "1. Добавить элемент " << endl;
cout << "2. Удалить элемент " << endl;
cout << "3. Заполнить список случайными числами " << endl;
cout << "4. Вывести список " << endl;
cout << "5. Удалить два наименьших и два наибольших элемента " << endl;
cout << "6. Выход " << endl;
int choise = correctInput("\nTURN: ");
switch (choise){
case 1:{
if (list_1.lenList == 0){
cout << "Список пуст." << endl;
int data = correctInput("Введите значение первого элемента: ");
Element *head_1 = head_1->create(data);
list_1.head = head_1;
list_1.lenList++;
}
else {
// cout << "Список непуст." << endl;
list_1.show();
cout << "[" << list_1.lenList << "] " << "вставить в конец " << endl;
int position = correctInput("\nВ какое место вставить элемен: ");
int data = correctInput("Введите значение элемента: ");
list_1.insert(position, data);
cout << "Готово!" << endl;
list_1.show();
}
break;
}
case 2:{
if (list_1.lenList == 0){
cout << "Список пуст, удалять нечего. " << endl;
}
else {
list_1.show();
int position = correctInput("\nВведите индекс удаляемого элемента: ");
list_1.del(position);
}
break;
}
case 3:{
cout << "Очищщаем предыдущий список. " << endl;
int length = correctInput("Введите количество элементов: ");
list_1.random(length);
break;
}
case 4:{
if (list_1.lenList == 0){
cout << " - Список пуст - " << endl;
}
else {
list_1.show();
}
break;
}
case 5:{
list_1.delete2b2m();
cout << "Результат: " << endl;
list_1.show();
break;
}
case 6:{
list_1.clear();
flag = 0;
break;
}
case 7:{
cout << "lenlist = " << list_1.lenList << endl;
break;
}
default:{
cout << "Неизвестный пункт " << endl;
break;
}
}
}
return 0;
}
int correctInput(const char str[]){
int x;
cout << str;
cin >> x;
while (cin.fail() || (cin.get() != '\n')){
cin.clear(); //сброс флага ошибки cin.fail;
cin.ignore(numeric_limits<streamsize>::max(),'\n'); //очистка потока от оставшихся символов
cerr << "Введено некорректное значение!" << endl;
cout << str;
cin >> x;
}
return x;
}