2014-01-03 4 views
2

Мне нужно настроить 1D-массив таким образом, чтобы он был гибким, чтобы переупорядочить, как при отбрасывании всех элементов k раз каждые следующие n элементов, а затем возврата к предыдущей структуре (вернуть удаленные элементы). Ниже приведен пример:Гибкий массив (или предлагать другую структуру данных)

p[10]={  //this is a one-dimensional array 
1, 2, 3, 4, 5 
4, 5 ,6, 7, 8} 


//push each 'row' 2 units back, every 5 elements. 
//"Row" here refers to the next nth element, here 5. 

<del>, <del>, 3, 4, 5 
<del>, <del> ,6, 7, 8 


//New structure 
<reserved>, <reserved>, 3, 4, 5 
<reserved>, <reserved>, 6, 7, 8 

//This is how it should look like in terms of data relevance, 
//with the reserved spaces not shown. 

    3, 4, 5 
    6, 7, 8 

Теперь p[0] должны быть 3 и p[3]=6.

Самый простой способ сделать это - создать новый массив с новыми элементами, но мне нужно сохранить старый и выполнить эти операции повторно в одном массиве, а затем вернуть его обратно в исходную структуру. Я думал, что может быть способ использования указателей, может быть, массив указателей, но я не совсем уверен. Если есть структура данных, которая делает это легко для меня, чем просьба указать мне.

+0

Что случилось с 'std :: vector' или, возможно,' std :: deque'? –

+0

Я не уверен в deque, но как бы я сделал это с помощью векторов? – user3140280

+0

взгляните на 'std :: valarray' – bolov

ответ

2

Вы можете сделать свой собственный класс, который будет представлять ваш массив и будет работать так, как вы этого хотите. Внутри он может иметь вектор всех элементов. Что-то в строках следующего кода.

Ваш заказ массив:

#include <iostream> 
#include <vector> 

    class Container 
{ 
public: 
    Container(int* buf, int len); 

    int operator[] (int i) { return buffer[validIndexes[i]]; } 

    void pushRowsBack(int n, int rowLength); 
    void restore(); 

    int size() { return validIndexes.size(); } 

private: 
    std::vector<int> buffer; 
    std::vector<int> validIndexes; 
}; 

реализация Конструктор (только пример, чтобы иметь рабочий пример):

Container::Container(int* buf, int len) 
    : buffer(buf, buf+len), 
    validIndexes(len, 0) 
{ 
    for (int i = 0; i < len; ++i) 
    { 
     validIndexes[i] = i; 
    } 
} 

pushBackRow() реализация:

void Container::pushRowsBack(int n, int rowLength) 
{ 
    int numRows = validIndexes.size()/(float)rowLength + 0.5; 
    std::vector<int>::iterator it = validIndexes.begin(); 

    // go through all the rows 
    for (int i = 0; i < numRows; ++i) 
    { 
     // erase the first n elements in the row 
     for (int j = 0; j < n; ++j) 
     { 
      it = validIndexes.erase(it); 
     } 

     // advance iterator to the next row 
     it += rowLength - n; 
    } 
} 

восстановления ():

void Container::restore() 
{ 
    validIndexes.resize(buffer.size()); 
    for (int i = 0; i < validIndexes.size(); ++i) 
    { 
     validIndexes[i] = i; 
    } 
} 

Пример использования:

void main() 
{ 
    int buffer[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; 

    Container c(buffer, 13); 

    c.pushRowsBack(2, 5); 
    for (int i = 0; i < c.size(); ++i) 
    { 
     std::cout << c[i] << ", "; 
    } 
    std::cout << std::endl; 

    c.restore(); 
    for (int i = 0; i < c.size(); ++i) 
    { 
     std::cout << c[i] << ", "; 
    } 
    std::cout << std::endl; 
} 

Входной сигнал:

1, 2, 3, 4, 5, 
6, 7, 8, 9, 10, 
11, 12, 13 

выход после того, как отодвигая строки с длиной 5 с помощью 2-х элементов:

3, 4, 5, 
8, 9, 10, 
13 

Выход после восстановления() :

1, 2, 3, 4, 5, 
6, 7, 8, 9, 10, 
11, 12, 13 
+0

Это именно то, что мне нужно. Кажется, перегрузка оператора [] была ключом. – user3140280

+0

Я рад, что это помогло :) – rozina

4

Для этого можно использовать vector. Он имеет push_back, pop_back, insert, erase и некоторые другие методы. Проверить здесь для получения дополнительной информации: http://www.cplusplus.com/reference/vector/vector/

vector<int> myArray; 

for(int i=0;i<8;i++) 
{ 
    myArray.push_back(i+1);//initialize 
} 

for(int i=0; i<8; i++) 
{ 
    //do something for finding the first 2 of each 5, (you can use mod 5) 
      myArray.erase(myvector.begin()+index) //removing 
} 
+0

Но как вернуть возвращаемые значения? – user3140280

+0

Вы можете сохранить их во временных переменных перед удалением из исходного вектора; или в временном векторе/массиве. затем восстанавливайте их, когда вам нужно. – biseibutsu

+1

** Предупреждение **: Будьте внимательны, чтобы правильно обновить 'index', чтобы учесть удаленный элемент (поэтому' index' не 'i', а' i - removedElementCount'). – Jarod42

0

Как было предложено Розина:

#include <cassert> 
#include <iostream> 
#include <vector> 

template <typename T> 
class ArrayView 
{ 
public: 
    explicit ArrayView(const std::vector<T>& v) : v(&v) { assert(this->v->size() % 5 == 0); } 

    const T& operator[] (std::size_t index) const { 
     const std::size_t newIndex = getCorrectedIndex(index); 

     return v->at(newIndex); 
    } 

    std::size_t size() const { return (v->size()/5) * 3; } 

private: 
    std::size_t getCorrectedIndex(std::size_t index) const { 
     return (index/3) * 5 + (index % 3) + 2; 
    } 
private: 
    const std::vector<T>* v; 
}; 


int main(int argc, char* argv[]) { 

    std::vector<int> v = {1, 2, 3, 4, 5, 
          4, 5, 6, 7, 8}; 
    ArrayView<int> a(v); 

    for (std::size_t i = 0, size = a.size(); i != size; ++i) { 
     std::cout << a[i] << " "; 
     if ((1 +i) % 3 == 0) { 
      std::cout << std::endl; 
     } 
    } 
    return 0; 
} 

выход:

3 4 5 
6 7 8 
1

Вы должны инкапсулировать свои данные в класс, который не ведет себя как обычный список (т. скрыть столбцы).Если вам требуется только удалить столбцы, то вы можете сделать это с чем-то вроде этого: (C++ 11)

#include <initializer_list> 

template <typename DataT, unsigned Rows, unsigned Cols> 
class Table 
{ 
public: 
    Table(const std::initializer_list<DataT>& list) { 
     int i = 0; 
     for (const DataT& item : list) 
      data[i++] = item; 
    } 
    void setFirstCol(unsigned v) { firstCol = v; } 
    DataT& operator[] (unsigned i) { 
     const unsigned c = Cols-firstCol; 
     return data[i/c*Cols + i%c + firstCol]; 
    } 
private: 
    unsigned firstCol = 0; 
    DataT data[Rows*Cols]; 
}; 

Использование:

int main() { 
    Table<int, 2, 5> table = { 
     1, 2, 3, 4, 5, 
     4, 5, 6, 7, 8 
    }; 

    cout << table[0] << endl; // 1 
    cout << table[5] << endl; // 4 

    table.setFirstCol(2); // you can undo this with setFirstCol(0); 

    cout << table[0] << endl; // 3 
    cout << table[3] << endl; // 6 
} 

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

template<DataT> 
struct Element { // store this struct in your array 
    DataT data; 
    bool deleted; 
}; 

и вы могли бы retrive элемент с чем-то похожее на это (обратите внимание на линейную ком сплетение):

DataT& operator[](unsigned i) { 
    for (Element& e : list) { 
     if (i == 0) return e; 
     if (!e.deleted) --i; 
    } 
    throw std::out_of_range("index is out of the container"); 
} 

Я думаю, что у вас есть идея.

Смежные вопросы