Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.68/69: Рейтинг темы: голосов - 69, средняя оценка - 4.68
iorange
0 / 0 / 0
Регистрация: 09.04.2011
Сообщений: 9
1

Удалить повторяющиеся элементы из массива

09.04.2011, 22:12. Просмотров 13926. Ответов 12
Метки нет (Все метки)

Требуется:
Удалить из 2-мерного массива повторяющиеся элементы, оставив только первое вхождение каждого элемента.
Количество элементов, а так же их значения вводить с клавиатуры, глобальные переменные не использовать.

Если интересно, есть готовый проверенный преподавателем алгоритм решения в псевдокоде. С него и переводил. Программированием ни в каком виде не занимался вообще никогда к сожалению, а вот теперь понадобилось.

На синтаксис компилятор ругаться перестал, но вот чего-то не хватает, потому как:
Если при вводе количества элементов ввести значение меньше "2" - программа прыгает на 2 последних сообщения ("повторов нет" и "конец") и завершается, а если больше 2 - то снова просит ввести количество элементов...
Подскажите, где еще что-то не так?

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <math.h>
void main ()
{
int n, i, j, k, f;
int mass [ 245 ];
 
    do  /* Цикл ввода количества элементов массива */
    {
        printf("\nВведите количество элементов массива (>1)\n");
        scanf("%d", &n);
        if(n<2)
        printf("\nНеверно. Повторите ввод\n");
    }
    while(n>=2);
 
    for(i=1;i<n; i++) /* Цикл ввода значений элементов */
    {
        printf("\nВведите значение элемента\n");
        scanf("%d", &mass[i]);
    }
 
    f=0; /* Сброс флага */
    for(i=1; i<=n-1; i++) /* Проверка элементов, перебор строк массива */
    {
     for (j=i+1; j<=n; j++) /* Перебор элементов строк */
        {
        if(mass[i]==mass[j]) /*  Нашли повтор */
            {
            for (k=j; k<=n; k++) 
            mass[k]=mass[k+1]; /* Сдвигаем все следующие элементы на 1 справа-налево */
            }
            n=n-1; /* "Укорачиваем" массив */
            j=j-1;
            f=1; /* Поднимаем флаг */
        }
    }
 
    if(f==1) /* Если были повторы - выводим новый массив, если не было - сообщение */
    {
        printf("\nПолученный массив имеет вид\n");
        for(i=1;i<=n;i++)
        printf("mass[i]");
    else
        printf("\nПовторений в массиве нет\n");
    }
printf("Конец");
}
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.04.2011, 22:12
Ответы с готовыми решениями:

Удалить повторяющиеся элементы из массива символов
Как удалить повторяющиеся элементы из массива символов? char str={&quot;abcdea&quot;};

Удалить повторяющиеся элементы из односвязного списка
Я написал программу, которая удаляет дубликаты в списки, оставляя только его первое вхождение. Но...

Удалить из массива повторяющиеся символы и отсортировать по алфавиту
Вообще задание звучит так: Разработать приложение, выполняющее следующие функции. Ввести с...

Найти повторяющиеся элементы массива
Есть одномерный массив надо выяснить сколько раз встречается пара таких же элементов. Например аа,...

Сравнить два массива, из большего вытащить не повторяющиеся элементы в новый
Есть задача Даны два целочисленных массива. Если размер первого массива больше размера второго, то...

12
lemegeton
2937 / 1366 / 467
Регистрация: 29.11.2010
Сообщений: 2,725
10.04.2011, 00:34 2
Не очень понятно, как именно удалять элементы двумерной матрицы.
Скажите, что будет с такими матрицами?

122
132
333
и
122
111
311
0
iorange
0 / 0 / 0
Регистрация: 09.04.2011
Сообщений: 9
10.04.2011, 01:16  [ТС] 3
Ну эти 2 превратятся в 123... Предполагается, что для пробы будет вводиться что-нибудь не настолько элементарное, но в разумных пределах разумеется (если сильно захотеть, можно и ограничения сразу поставить).
Мне сейчас интереснее всего, что не так в моем коде - почему при выполнении игнорируются 16-45 строки напрочь?
Ну удаление это наверно не совсем правильный термин. Надо сдвигать на одну позицию налево все последующие элементы и уменьшать значение их общего количества.

На псевдокоде алгоритм действий выглядит так:
Код
Алгоритм (удаление повторяющихся элементов массива путем сдвига на 1 символ)
Начало
Целые n, массив A, i, j, k, flag
	цикл
		вывод «Введите количество элементов массива А (>1)»
		ввод n
		если n<2 то
			вывод «Неверно. Повторите ввод»
		все
	конец цикла при n>=2
	вывод «Введите значение элементов массива»
	цикл для i от 1 до n
		ввод a[i]
	конец цикла
	flag:=0
	цикл для i от 1 до (n-1)
		цикл для j=(i+1) до n с шагом 1
			если a[i]=a[j] то
				цикл для k=j до n с шагом 1
				a[k]:= a[(k+1)]
				конец цикла
				n:=n-1
				j:= j-1
				flag:=1
			всё
		конец цикла
	конец цикла
	если flag:=1 то
		вывод «Полученный массив имеет вид»
		цикл для i от 1 до n
			вывод a[i]
		конец цикла
	иначе 
		вывод «Повторений в массиве нет»
	всё
	вывод «Конец»
конец алгоритма
Тестовый пример работы алгоритма прикреплю в виде pdf, он таблицей для наглядности расписан.
Смотреть таблицу надо слева-направо сверху по столбцам.
0
Вложения
Тип файла: pdf разбор тестового примера.pdf (342.1 Кб, 102 просмотров)
vitaska
90 / 90 / 15
Регистрация: 04.02.2010
Сообщений: 162
10.04.2011, 01:27 4
причем тут двумерный массив понять не могу, так как псевдокод приведен для одномерного массива
0
iorange
0 / 0 / 0
Регистрация: 09.04.2011
Сообщений: 9
10.04.2011, 13:31  [ТС] 5
Да, точно... Массив одномерный...
Но вопроса это не отменяет.
Что в коде не так? Почему 16...45 строки не выполняются и что исправить, чтобы они выполнялись?
0
vitaska
90 / 90 / 15
Регистрация: 04.02.2010
Сообщений: 162
10.04.2011, 13:56 6
Цитата Сообщение от iorange Посмотреть сообщение
C
1
2
3
4
5
6
7
8
do /* Цикл ввода количества элементов массива */
 {
 printf("\nВведите количество элементов массива (>1)\n");
 scanf("%d", &n);
 if(n<2)
 printf("\nНеверно. Повторите ввод\n");
 }
 while(n>=2);
условие измените на n<2

Цитата Сообщение от iorange Посмотреть сообщение
C
1
for(i=1; i<=n-1; i++) /* Проверка элементов, перебор строк массива */
индексация массивов начинается c 0 а не с 1
C
1
for(i=0; i<n; i++)
1
iorange
0 / 0 / 0
Регистрация: 09.04.2011
Сообщений: 9
18.04.2011, 00:17  [ТС] 7
С кодом разобрался, теперь это выглядит так:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdio.h>
#include <math.h>
#include <conio.h>
 
void main ()
{
int n, i, j, k, f;
int mass [ 245 ];
clrscr();
do
    {
        printf("\nVvedite kolichestvo elementov massiva (>1)\n");
        scanf("%d", &n);
        if(n<2)
        printf("\nNeverno! Povtorite vvod\n");
    }
    while(n<2);
    for(i=0; i<n; i++)
    {
        printf("\nVvedite znachenie elementa\n");
        scanf("%d", &mass[i]);
    }
 
    printf("\nVvedenniy massiv imeet vid:\n");
    for(i=0; i<n; i++)
    printf("%d\t", mass[i]);
    f=0;
    for(i=0; i<n; i++)
    {
    for(j=i+1; j<=n; j++)
        {
        if(mass[i]==mass[j])
            {
            for(k=j; k<=n; k++)
            mass[k]=mass[k++];
            n=n-1;
            j=j-1;
            f=1;
            }
        }
    }
    if(f==1)
    {
        printf("\nPoluchennyi massiv imeet vid:\n");
        for(i=0; i<=n; i++)
        printf("%d\t", mass[i]);
    }
    else
    {
        printf("\nPovtorenii v massive net.\n");
    }
    printf("\nKonec\n");
}
Новая проблема:
если в тестовом примере в массиве больше 5 элементов и среди элементов есть 0 но нет повторений, то выводится не сообщение "Повторений нет", а "Полученный массив имеет вид" и тот же самый массив.
0
popov654
32 / 32 / 7
Регистрация: 09.04.2011
Сообщений: 119
18.04.2011, 03:44 8
1) Не советовал бы использовать mass[k++], поскольку насколько я знаю Вы тем самым меняете значение k, что в цикле делать не есть хорошо
2) В строке 34 я бы сделал for(k=j; k<=n-1; k++) чтобы не выходить за границы массива
0
iorange
0 / 0 / 0
Регистрация: 09.04.2011
Сообщений: 9
19.04.2011, 23:00  [ТС] 9
Цитата Сообщение от popov654 Посмотреть сообщение
1) Не советовал бы использовать mass[k++], поскольку насколько я знаю Вы тем самым меняете значение k, что в цикле делать не есть хорошо
2) В строке 34 я бы сделал for(k=j; k<=n-1; k++) чтобы не выходить за границы массива
после этих поправок стало еще хуже, теперь если среди элементов есть 2 ноля - программа застопоривается после вывода "введенный массив имеет вид" и из TC, и как самостоятельный "exe"
0
popov654
32 / 32 / 7
Регистрация: 09.04.2011
Сообщений: 119
20.04.2011, 03:12 10
iorange, хуже стать не могло. Это совершенно точно.
У Вас проблема была в чём? Массив с нулём засчитывался как массив с повтором. Так это потому что Вы нарушили границы индексации, компилятор это как-то слопал (видимо в Си нет проверки на границы массива, как в Паскале и Java, что скверно). А у Вас 0 наверное был последним, вот Вы и попали на ячейку памяти за Вашим массивом и там тоже оказался 0. Насчёт инкремента - то же самое, у Вас в самой первой версии кода его не было (было k+1), и это совершенно правильно.

Насчёт почему не работает сейчас - трудно сказать, но я вот ещё вижу что у Вас <=, а должно быть строго < в том самом цикле. Простите, в первый раз проглядел. Попробуйте поправьте... посмотрим чего будет.

Добавлено через 25 минут
iorange, я вот даже специально для того чтобы проверить Ваш код поставил компилятор
Вы знаете, код меня крайне позабавил) Точнее, результат. Вы говорили,всё нормально, когда нет нулей? Как Вам 1 3 3 5 2 -> 1 3?

Добавлено через 16 минут
Вот, принимайте :

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <stdio.h>
#include <math.h>
 
 
int main ()
{
    int n, i, j, k, f;
    int mass[245];
    //clrscr();
    do {
       printf("\nVvedite kolichestvo elementov massiva (>1)\n");
       scanf("%d", &n);
       if(n<2)  printf("\nNeverno! Povtorite vvod\n");
    } while (n<2);
 
    printf("\nVvedite znacheniya elementov chehrez probel:\n");
    for(i=0; i<n; i++) { 
        scanf("%d", &mass[i]);
    }
 
    printf("\nVvedenniy massiv imeet vid:\n");
    for(i=0; i<n; i++)
        printf("%d ", mass[i]);
    f=0;
    for(i=0; i<n; i++) {
        for(j=i+1; j<n; j++) {
            if(mass[i]==mass[j]) {
                for(k=j; k<n-1; k++)
                        mass[k]=mass[k+1];
                n--;
                f=1;
            }
        }
    }
    if(f==1) {
        printf("\nPoluchennyi massiv imeet vid:\n");
        for(i=0; i<n; i++)
            printf("%d ", mass[i]);
    }
    else {
        printf("\nPovtoreniy v massive net.\n");
    }
    getchar();
    getchar();
    return 0;
}
Ну я тут под себя немного ввод/вывод переделал... #include <conio.h> верните, у меня просто на неё Dev-Cpp ругается. clrscr() я даже удалять не стал, просто закомментировал
Тестировал на разных массивах. Работает
3
iorange
0 / 0 / 0
Регистрация: 09.04.2011
Сообщений: 9
21.04.2011, 01:12  [ТС] 11
Цитата Сообщение от popov654 Посмотреть сообщение
Вот, принимайте
...
Тестировал на разных массивах. Работает
Спасибо за поправки!
Я тоже потестировал немножко и убедился, что 37 строчку
C
1
j=j-1;
вы зря выкинули, без нее такое вот безобразие выходит)) ( ну а с ней, соответственно "1 2 2 2 3 1 2 3" превращается в правильное "1 2 3")

а в остальном все хорошо, да)) на 0 больше не залипает и вообще правильно работает похоже)) спасибо!!
0
Миниатюры
Удалить повторяющиеся элементы из массива  
popov654
32 / 32 / 7
Регистрация: 09.04.2011
Сообщений: 119
21.04.2011, 01:21 12
Да, Вы правы) Погорячился
Я только сейчас понял, что именно Вы ей делали... И почему без неё плохо. Я не учёл того, что после сдвига внешний цикл for принудительно сдвинет j (а нам этого не надо). Вот мы и делаем такой "противовес". Да, нестандартный приём)

А я как-то всегда с осторожностью относился к переменной-итератору внутри цикла, нас как-то запугали ещё в школе, чтобы мы не вздумаи с ней чего-нибудь производить. Да и сам не раз обжигался. Поэтому эта операция и смутила . На самом деле тут всё хорошо
0
iorange
0 / 0 / 0
Регистрация: 09.04.2011
Сообщений: 9
21.04.2011, 18:49  [ТС] 13
а меня программированию никто никогда не учил

Спасибо еще раз за помощь!
0
21.04.2011, 18:49
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.04.2011, 18:49

Вывести упорядоченные по убыванию повторяющиеся элементы массива и число повторений
Выдает ошибку в коде: Нужно: Вывести упорядочены по убыванию повторяющиеся элементы произвольного...

Вывести упорядоченные по убыванию повторяющиеся элементы произвольного одномерного массива
Вывести упорядочены по убыванию повторяющиеся элементы произвольного одномерного массива целых...

Сортировка элементов массива так, что сначала идут все повторяющиеся элементы
Привет всем, может кто-то уже сталкивался с такой задачей, вводим элементы массива, на выходе...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru