Scratch Data Structure (ii) an ordered array

By definition is an ordered array of all permutations of elements in the array are in a certain order. No matter how many elements are inserted, ordered array elements are automatically inserted into the appropriate location. Here we must achieve is a fixed length of an ordered array.

I. ordered array COrderArray class

To achieve an orderly array, the array should first consider what functions should be achieved:
1. constructor to initialize the array, the array to the specified length given.
2. Insert the data, the most important function, data is automatically inserted into the lined order.
3. Find the specified value, orderly array has a very important feature that is very easy to find a particular value.
4. Find the specified position, corresponding to this element is overloaded functions [] subscript operator, so that the array can be the same as a normal ordered array subscript access.
5. Delete the element at the location.
6. remove elements specified value.
7. Empty all the elements.
8. merge two ordered arrays, this feature is also a type of brush subject algorithm problems you might encounter.

Reason clearly about what kind of functions to achieve, you can begin to write a function declaration header file.

#pragma once
#include "CArray.h"
class COrderArray ://依然是继承数组基类
    public CArray
{
public:
    COrderArray(int size);//构造函数
    void PushBack(int value);//插入数据
    void RemoveForValue(int value);//根据指定值删除数组元素
    void RemoveForPos(int pos);//根据指定位置删除数组元素
    int FindForValue(int value);//根据指定值查找数组元素
    int &operator[](int pos);
    //重载下标运算符,达到按位置操作数组元素的目的
    //重载下标运算符的时候,这里的返回值必须是引用类型
    void Clear();//清空所有元素
    void Merge(COrderArray& array);//合并两个有序数组
private:
    void _InsertElement(int value, int start);
    //因为在数组中插入值的时候会将该位置后的所有的元素都向后移一个位置,参数为插入值和后移的初始位
    //所以单独写一个私有函数来完成插入并后移的功能,防止函数体内容太多,该函数也是不能在外部去调用
    void _RemoveElement(int pos);
    //和上面同理,这个函数是用来删除数组中某个位置的元素,删除完成后把该位置后面的元素前移
    
    //注意:这两个函数和上面的的插入、删除函数的不同之处在于上面两个公有函数负责给用户调用
    //并且实现用什么样的策略去删除或者插入,它们是内部调用下面的两个私有函数
    //而这两个私有函数只是是完成插入和删除的功能
};

Other member functions and member variables in an array CArray base class has been defined, do not write here.

Specific implementation class two .COrderArray

1. constructor
because it is an ordered array of fixed length, the constructor requires a given n, then the capacity of the array is set n

COrderArray::COrderArray(int size)
{
    m_Capacity = size;
    mp_Array = new int[m_Capacity];
}

2. Insert the elements of
an ordered array of each insert an element to be considered inserted position, ensure that the entire array is still ordered after insertion. So should insert an element before the current element to insert and already have an array element size comparison. Sequence comparison methods can be employed, i.e., from start comparing the smallest element.
But because this is an ordered array, comparing sequential mode will seem very cumbersome, here is the best use dichotomy. I.e. first determining an initial position and the end position, and two intermediate positions of the element. If the element to be inserted is larger than the intermediate element, put the start bit set to re-present an intermediate position, and then recalculates the new intermediate position, and then comparing the intermediate position. The advantage is soon to find a suitable insertion position.

//插入元素,判断元素大小来决定其应该在数组中位置
void COrderArray::PushBack(int value)
{
    //数组元素个数已经达到数组最大容量,直接返回
    if (m_Size == m_Capacity)
    {
        return;
    }

    //二分查找
    int start = 0;
    int end = m_Size;
    int mid = (start + end) / 2;
    while (1)
    {
        //数组还没有元素的时候,直接插入
        if (m_Size == 0)
        {
            mp_Array[m_Size] = value;
            break;
        }
        //循环跳出的条件,即mid与首尾之一相等
        if (mid==start||mid==end)
        {
            if (mp_Array[mid] > value)//如果最后一次循环时,mid位置的元素大于插入位置的元素
            {
                _InsertElement(value, mid);//对当前mid位置,调用插入元素的函数
                break;
            }
            //若最后一次循环时,mid位置元素小于插入位置的元素
            //对mid位置后面的一个位置,调用插入元素的函数   
            _InsertElementvalue, mid + 1);
            
            break;
        }
        //二分法,比较插入元素和中间元素的大小,然后改变mid的值
        if (mp_Array[mid] > value)//插入元素比中间元素小,end改为mid,mid根据新的end更新一下
        {
            end = mid;
            mid = (start + end) / 2;
        }
        else//插入元素比中间元素大,start改为mid,mid根据新的start更新一下
        {
            start = mid;
            mid = (start + end) / 2;
        }
    }
    m_Size++;
}

Dichotomy process is more suitable on paper drawn step by step, it is easy to understand this process.
In just a function of the realization of a just insert elements should be inserted to search for the position, actually did not complete the insert, so at the end of the cycle also called _InsertElement (value, mid), to complete the insertion and the insertion position All the elements were behind after a move.
** _ InsertElement function is as follows: **

//在数组中要插入的元素位置之后的所有元素进行后移
void COrderArray::_InsertElement(int value, int pos)
{
    for (int i = m_Size; i > pos; i--)
    {
        mp_Array[i] = mp_Array[i - 1];
    }
    mp_Array[pos] = value;
}

Here only need inserted location, a loop for moving all the elements back to one, and then to insert a new element.

3. Find the value specified element
similar to the method above and the elements to find the value, using a binary search.

//根据值查找,二分查找,和上面的插入类似
int COrderArray::FindForValue (int value)
{
    int start = 0;
    int end = m_Size;
    int mid = (start + end) / 2;
    while (mid != start && mid != end)
    {
        if (mp_Array[mid] == value)
        {
            return mid;
        }
        if (mp_Array[mid] > value)
        {
            end = mid;
            mid = (start + end) / 2;
        }
        else
        {
            start = mid;
            mid = (start + end) / 2;
        }
    }
    if (mp_Array[mid] == value)
    {
        return mid;
    }
}

The lookup element specified position
which is actually a function of the array index and subscripts are the same, so this place can not write function, but the subscript operator overloading. Before writing dynamic arrays can also add this feature.

int &COrderArray::operator[](int pos)
{
    if (pos > m_Size || pos < 0)
    {
        return mp_Array[0];
    }
    return mp_Array[pos];
}

Overload subscript operator when the return value is a reference type, but is preferably made of a bounds check, if the index is out of range index, returns the first element of the array.

5. Clear all the elements
and similar dynamic array element empty, the current number of elements need only to zero.

//清空所有元素
void COrderArray::Clear()
{
    m_Size = 0;
}

6. Specify the location to remove elements based on
all the elements behind the position of the deleted array elements according to the specified position just need to be deleted are moved forward one position, so that automatically covers the element to be deleted. And written in front _RemoveElement (int pos) function function is to remove elements and specify the location of the element after moving forward, all this can be considered directly call this function.
** _ RemoveElement (int pos) as follows: **

//删除操作,把删除的数后面每一个元素向前移动一个位置
void COrderArray::_RemoveElement(int pos)
{
    if (pos >= 0 && pos < m_Size)
    {
        for (int i = pos; i < m_Size; i++)
        {
            mp_Array[i] = mp_Array[i + 1];
        }
        m_Size--;
    }
}

Remove elements function according to the specified location:

//根据指定位置删除元素
void COrderArray::RemoveForPos(int pos)
{
    _RemoveElement(pos);
}

The specified value delete elements
specified value array to the specified value to delete elements in the array, first of all but it is still to be found, it can be written directly in front of lookup function specified value, use a variable to receive the return position, call later found in front of the _RemoveElement (int pos) function can be.

//根据指定值删除元素
void COrderArray::RemoveForValue(int value)
{
    int pos = FindForValue(value);
    _RemoveElement(pos);
}

8. merging two sorted array
to achieve ordered merge two arrays, there are several ways of thinking, is to use a new object to the combined package the sorted array, this overhead is relatively large. So here to choose the first ordered array and a second ordered array which are merged into a first and a second array does not change. So the parameters of the function should be the second ordered array.
That Merge (COrderArray & tempArray)
Note the use of a COrderArray &, which is a reference. When the class object of function parameter usually used when the reference, because the use of a reference copy constructor does not call, but direct operation of the original object, which can reduce the cost of the program.
Meanwhile, if there are contained in the object out of the new pointer, must be used to pass parameters by reference. Because the value passed will generate a copy of the object, the destructor will automatically executed at the end of, the original target will delete the pointer out of the new off. While at the end of the process, one will call the destructor, delete duplicate this same pointer, will run error. Be referenced as a parameter is not generated copy of the object, it does not call the destructor. Of course, if the object itself is not a variable dynamically created, not a value passed much of a problem.
The main idea is merging two arrays in turn than the size, small on the first into the new array, and then continue to lose out.
Because here is to create a fixed-length array, so you have to open a new, larger memory space, it is the size of the sum of two arrays capacity, so the merger the combined forward from here should be better.

//合并两个有序数组
void COrderArray::Merge(COrderArray& tempArray)
{
    //开一个新的内存来存储合并后的数组,首先需要计算新的内存需要多大
    int tempArrayCapacity = tempArray.getCapacity();
    int newCapacity = tempArrayCapacity + m_Capacity;
    int* newSpace = new int[newCapacity];

    //因为原来数组的元素有可能没有满
    //所以要从两个数组当前size的位置开始合并
    //tempsize即两个数组的size之和
    //pos是合并的时候的一个索引,每取出来一个元素,就放到newSpace[pos],并-1,到0的时候就合并完
    int tempArraySize = tempArray.getSize();
    int tempSize = tempArraySize + m_Size;
    int pos = tempSize - 1;//索引要-1

    //开始合并
    while (pos >= 0)
    {
    //如果第一个数组元素个数不为0才进行比较
        if (m_Size != 0)
        {
            //第一个数组元素大于传参进来的数组元素
            //或者第二个数组元素索引已经比较到0
            //第一个数组的元素放进新开的内存空间,然后size-1
            if (mp_Array[m_Size - 1] >= tempArray[tempArraySize - 1])
            {
                newSpace[pos] = mp_Array[m_Size - 1];
                m_Size--;
            }
            else
            {
                newSpace[pos] = tempArray[tempArraySize - 1];
                tempArraySize--;
            }
        }else//如果第一个数组元素个数已经为0,直接把另一个数组的元素按顺序放进来,不需要再进行比较
        {
            newSpace[pos] = tempArray[tempArraySize - 1];
            tempArraySize--;
        }
        pos--;
    }
    //清理掉要合并数组的原来的内存
    //把size设置为新的合并后的size
    //数组容量设置为新的容量
    //指针要指向新的存放数据的内存空间
    delete[] mp_Array;
    m_Size = tempSize;
    m_Capacity = newCapacity;
    mp_Array = newSpace;
}

Here, all the functions of an ordered array to achieve completed, the next main function is to call this an ordered array.

Three main functions Array.cpp

The main function is to create two major ordered array object, and then insert the data, you can see inserted data are ordered, and then merge the two ordered arrays.

#include<iostream>
using namespace std;
#include "COrderArray.h"
using namespace std;
int main()
{
    int n;
    cin >> n;

    //COrderArray* oArray = new COrderArray(n);
    COrderArray oArray(n);
    COrderArray oArray2(n);
    //插入第一个数组的数据
    for (int i = 0; i < n; i++)
    {
        int temp;
        cin >> temp;
        oArray.PushBack(temp);
    }
    //插入第二个数组的数据
    for (int i = 0; i < n; i++)
    {
        int temp;
        cin >> temp;
        oArray2.PushBack(temp);
    }
    oArray.Print();//打印数组
    
    oArray.Merge(oArray2);//合并两个数组
    oArray.Print();//重新打印
    return 0;
}
输入数据:
6
9 4 6 11 5 8
7 10 6 18 2 4

输出数据:
print all date :
4
5
6
8
9
11

合并数组后的输出数据:
print all date :
2
4
4
5
6
6
7
8
9
10
11
18

This realization of an ordered array on, this place is just as before as type int array, and did not use a template, it is also open to expansion, to achieve more functionality. Finally, the code of all files.

All source code files

All the code COrderArray.h file is as follows:

#pragma once
#include "CArray.h"
class COrderArray ://依然是继承数组基类
    public CArray
{
public:
    COrderArray(int size);//构造函数
    void PushBack(int value);//插入数据
    void RemoveForValue(int value);//根据指定值删除数组元素
    void RemoveForPos(int pos);//根据指定位置删除数组元素
    int FindForValue(int value);//根据指定值查找数组元素
    int &operator[](int pos);
    //重载下标运算符,达到按位置操作数组元素的目的
    //重载下标运算符的时候,这里的返回值必须是引用类型
    void Clear();//清空所有元素
    void Merge(COrderArray& array);//合并两个有序数组
private:
    void _InsertElement(int value, int start);
    //因为在数组中插入值的时候会将该位置后的所有的元素都向后移一个位置,参数为插入值和后移的初始位
    //所以单独写一个私有函数来完成插入并后移的功能,防止函数体内容太多,该函数也是不能在外部去调用
    void _RemoveElement(int pos);
    //和上面同理,这个函数是用来删除数组中某个位置的元素,删除完成后把该位置后面的元素前移
    
    //注意:这两个函数和上面的的插入、删除函数的不同之处在于上面两个公有函数负责给用户调用
    //并且实现用什么样的策略去删除或者插入,它们是内部调用下面的两个私有函数
    //而这两个私有函数只是是完成插入和删除的功能
};

All the code COrderArray.cpp file is as follows:

#include<iostream>
#include "COrderArray.h"
COrderArray::COrderArray(int size)
{
    m_Capacity = size;
    mp_Array = new int[m_Capacity];
}

//在数组中要插入的元素位置之后的所有元素进行后移
void COrderArray::_InsertElement(int value, int pos)
{
    for (int i = m_Size; i > pos; i--)
    {
        mp_Array[i] = mp_Array[i - 1];
    }
    mp_Array[pos] = value;
}

//插入元素,判断元素大小来决定其应该在数组中位置
void COrderArray::PushBack(int value)
{
    if (m_Size == m_Capacity)
    {
        return;
    }

    //二分查找
    int start = 0;
    int end = m_Size;
    int mid = (start + end) / 2;
    while (1)
    {
        //数组还没有元素的时候,直接插入
        if (m_Size == 0)
        {
            mp_Array[m_Size] = value;
            break;
        }
        //循环跳出的条件,即mid与首尾之一相等
        if (mid==start||mid==end)
        {
            if (mp_Array[mid] > value)
            {
                _InsertElement(value, mid);
                break;
            }
            _InsertElement(value, mid + 1);
            break;
        }
        //大小判别,然后改变mid的值进行二分
        if (mp_Array[mid] > value)
        {
            end = mid;
            mid = (start + end) / 2;
        }
        else
        {
            start = mid;
            mid = (start + end) / 2;
        }
    }
    m_Size++;
}

//根据值查找,二分查找,和上面的插入类似
int COrderArray::FindForValue (int value)
{
    int start = 0;
    int end = m_Size;
    int mid = (start + end) / 2;
    while (mid != start && mid != end)
    {
        if (mp_Array[mid] == value)
        {
            return mid;
        }
        if (mp_Array[mid] > value)
        {
            end = mid;
            mid = (start + end) / 2;
        }
        else
        {
            start = mid;
            mid = (start + end) / 2;
        }
    }
    if (mp_Array[mid] == value)
    {
        return mid;
    }
}

//删除操作,把删除的数后面每一个元素向前移动一个位置
void COrderArray::_RemoveElement(int pos)
{
    if (pos >= 0 && pos < m_Size)
    {
        for (int i = pos; i < m_Size; i++)
        {
            mp_Array[i] = mp_Array[i + 1];
        }
        m_Size--;
    }
}

//根据指定位置删除元素
void COrderArray::RemoveForPos(int pos)
{
    _RemoveElement(pos);
}

//根据指定值删除元素
void COrderArray::RemoveForValue(int value)
{
    int pos = FindForValue(value);
    _RemoveElement(pos);
}
//重载下标运算符
int &COrderArray::operator[](int pos)
{
    if (pos > m_Size || pos < 0)
    {
        return mp_Array[0];
    }
    return mp_Array[pos];
}
//清空所有元素
void COrderArray::Clear()
{
    m_Size = 0;
}
//合并两个有序数组
void COrderArray::Merge(COrderArray& tempArray)
{
    //开一个新的内存来存储合并后的数组,首先需要计算新的内存需要多大
    int tempArrayCapacity = tempArray.getCapacity();
    int newCapacity = tempArrayCapacity + m_Capacity;
    int* newSpace = new int[newCapacity];

    //从两个数组当前size的位置开始合并
    int tempArraySize = tempArray.getSize();
    int tempSize = tempArraySize + m_Size;
    int pos = tempSize - 1;
    while (pos >= 0)
    {
        if (m_Size != 0)
        {
            if (mp_Array[m_Size - 1] >= tempArray[tempArraySize - 1]|| tempArraySize==0)
            {
                newSpace[pos] = mp_Array[m_Size - 1];
                m_Size--;
            }
            else
            {
                newSpace[pos] = tempArray[tempArraySize - 1];
                tempArraySize--;
            }
        }else
        {
            newSpace[pos] = tempArray[tempArraySize - 1];
            tempArraySize--;
        }
        pos--;
    }
    delete[] mp_Array;
    m_Size = tempSize;
    m_Capacity = newCapacity;
    mp_Array = newSpace;
}

All the code Array.cpp file is as follows:

#include<iostream>
using namespace std;
#include "COrderArray.h"
using namespace std;
int main()
{
    int n;
    cin >> n;

    //COrderArray* oArray = new COrderArray(n);
    COrderArray oArray(n);
    COrderArray oArray2(n);
    //插入第一个数组的数据
    for (int i = 0; i < n; i++)
    {
        int temp;
        cin >> temp;
        oArray.PushBack(temp);
    }
    //插入第二个数组的数据
    for (int i = 0; i < n; i++)
    {
        int temp;
        cin >> temp;
        oArray2.PushBack(temp);
    }
    oArray.Print();//打印数组
    
    oArray.Merge(oArray2);//合并两个数组
    oArray.Print();//重新打印
    return 0;
}

Guess you like

Origin www.cnblogs.com/nsytsqdtn/p/11387654.html