Function that checks if an array is sorted - c++

So I'm just a beignner programmer when it comes to C++, and I have to write a function that checks if an int array is sorted using pointers (no index notations allowed), and here's what I have so far:
bool isSorted(const int *ar, int size) {
bool sorted = true;
const int *ptr1, *ptr2, *ptr3;
ptr1 = ar;
ptr2 = ar+1;
ptr3 = ar+size;
for (ptr1; ptr1 < ptr3; ptr1++) {
for (ptr2; ptr2 < ptr3; ptr2++) {
if (*ptr1 > *ptr2) {
sorted = false;
}
}
}
return sorted;
}
However, I can't seem to get it to work as it always returns true regardless of whether the array is sorted or not. Any help is appreciated, thanks.

"The more you overthink the plumbing, the easier it is to stop up the
drain" -- Scotty, Star Trek III.
You are making this much more complicated than it has to be.
Ask yourself a basic question: what is a sorted array?
Answer: an array in which each successive element is not less than its preceding element.
Therefore: to check if the array is sorted, just look for an element that's less than its previous element. If you found one, the array is not sorted. If you couldn't find one, the array must be sorted.
bool isSorted(const int *ar, int size) {
if (size == 0)
return true; // Edge case
int previous_value= *ar;
while (size)
{
if (*ar < previous_value)
return false;
previous_value= *ar;
++ar;
--size;
}
return true;
}
No index notations, just a single pointer. No need to do any kind of a nested search, etc... If you want to use only pointers, you could do this:
bool isSorted(const int *ar, int size) {
const int *previous_value=ar;
while (size)
{
if (*ar < *previous_value)
return false;
previous_value= ar;
++ar;
--size;
}
return true;
}
Actually, I like this version even better.

You should keep ptr2 always be ptr+1,so you need to initialize ptr2 in second for() .
And I think only one loop is better.
for(; ptr2 < ptr3; ++ptr1, ++ptr2) {
if (*ptr1 > *ptr2) {
sorted = false;
}
}
return sorted;

Related

recursive binary search in c++ using a bool function

I have an school assignement that requires me to create a recursive Binary search function. I'm not allowed to change the function signature.
My experience with pointer isn't the best and i think my problem lies there.
I get an Stackoveflow but i dont really understand way
bool contains(const int* pBegin, const int* pEnd, int x)
{
int length = pEnd - pBegin;//gives me the length of the array
const int* pMid = pBegin + (length / 2);
if(length == 1)
{
if(*pMid != x)
return false;
return true;
}
else if(x < *pMid)
return contains(pBegin, pMid-1, x);
else
return contains(pMid, pEnd, x);
}
void main(){
setlocale(LC_ALL, "swedish");
int arr[10];
for(int i = 0; i < 10; ++i)
arr[i] = i;
bool find = contains(&arr[0], &arr[10], 3);//arr[10] points to the index after the array!
cout <<"found = "<< find << endl;
system("pause");
}
Can somebody please explain to me what I'm doing wrong, and how i could do it in a better way?
Stack overflow is due to too deep recursion.
Its unlikely your array is large enough to really be a problem, so what you have is unbounded recursion ... contains() keeps calling itself and fails to detect this.
Look at how this is possible, and add assertions.
Your code assumes
pEnd > pBegin
Your code doesn't handle this possibility.
#include <assert.h>
bool contains( ... )
{
assert(pBegin > pEnd);
...
Now, it will abort if this assumption is incorrect.
There are two possibities for (pEnd > pBegin) being false, namely "<" or "==".
What does your code do in these two cases?
Spoiler below..
Length can be zero and isn't handled.

Linked list without struct

Can anyone help me with a singly linked list? I know how to do it with struct, but now i wanna know how to do it with only arrays and pointers without struct or nodes.Algorithms please thank you.
#include <iostream>
using namespace std;
const int size=5;
int data[size];
int *mem;
int add[size];
int top = -1;
void AddLast(int value)
{
if(top==-1)
{
top=data[value];
}
else
{
top++;
top=data[value];
}
}
void print()
{ cout << "Queue: ";
for(int i = 0; i != top; i = (i + 1) % size)
{
cout << data[i] << "->";
}
cout << endl;
}
int main()
{
AddLast(2);
print();
AddLast(3);
print();
AddLast(4);
print();
cin.get();
return 0;
}
I want to addlast, addfirst, and add sorted... is this the way?
You can't do it with only one array, you need at least two: One for the data and one for the links. If you don't want to use structures at all (though I don't really see the reason for it) you could have multiple data arrays.
The data array contains the actual data, it's nothing special with it. The link array contains indexes to the data array, where each index is a "next" pointer.
For example, lets say you want to have a linked list of integers, and you have three integers in the list (their values are irrelevant), lets call that data array d, then you have d[0], d[1] and d[2]. The first node in the list is d[1], followed by d[0] and last d[2]. Then you need a head variable, which tells which index is the head of the list, this head variable is initialized to 1 (and "points" to d[1]). Then we have the link array, lets call it l, since the head is "pointing" to 1 we fetch l[1] to get the next node, the contents of l[1] is 0 which tells us the next node is d[0]. To get the next node we check l[0] which gives us 2 for d[2]. The next link, l[2] could be -1 to mark the end of the list.
Of course, the data array(s) and the link array needs to be of the same size.
An array s of structs with members A, B, C, can be emulated by three arrays a, b and c, where e.g. a[i] represents s[i].A, and so forth. So that's your requirement of no structs. Then doing a linked list with arrays, i.e. with indices instead of pointers, is mere notation; the concepts are exactly the same. But you might look up the technique of using a free list, a list of available logical nodes; this allows you to free nodes as well as allocate them, in a simple way.
There is a (ugly) way to do a linked list with arrays.
Here is an example of how you might do something with arrays but I would never recommend even thinking about doing it.
template<class T>
typedef char[sizeof(T) + sizeof(uintptr_t)] listNode;
template<class T>
listNode<T>* getNext(const listNode<T>& x){
return (listNode<T>*)(((char*)x)[sizeof(T)]); //notice how you have to increment the pointer address
}
template<class T>
T& getValue(listNode<T>& x){
return (T) x;
}
That's way too many casts. It's less ugly if you make an array of two pointers and just cast the first value in a pointer on what you care about but that's still not what I would recommend.
This is a hack of sorts might help with your curiosity.
It is similar in implementation to how linked lists are typically implemented with struct.
#include<stdio.h>
#include<stdlib.h>
int * base = NULL;
int ** current = NULL;
void add(int num)
{
if(base==NULL)
{
base = (int*)malloc(sizeof(int)*3);
base[0] = num;
current = (int**)(base+1);
current[0] = NULL;
}
else
{
current[0] = (int*)malloc( sizeof(int)*3 );
current[0][0] = num;
current = (int**)(*current+1);
current[0] = NULL;
}
}
void show()
{
if(base != NULL)
{
int * data = base;
int ** tmp = (int**)(base+1);
if(tmp[0]==NULL)
printf("%d\n",data[0]);
else
{
do
{
printf("%d ",data[0]);
data = tmp[0];
tmp = (int**)(data+1);
}while(tmp[0]!=NULL);
printf("%d\n",data[0]);
}
}
}
int main()
{
int choice,num;
do
{
scanf("%d",&choice);
switch(choice)
{
case 1:scanf("%d",&num);
add(num);
break;
case 2:show();
}
}while(1);
return 0;
}
It is possible to add other function like addFirst() or addSorted() but will require some more pointer manipulation, for which I don't possess the dedication right now.

Cplusplus std::set of bidimensional array

I'm new to C++ and I need to use Set from the STL but I'm struggling with the concept.
I have an array like this int my_data[3]
I want to create (don't know if this is possible) a set with space for 3 ints and that the key for the set would be the int that is stored on the first column.
I also want to make a custom sort.
This is what I've tried but with no success.
struct sort_set {
bool operator() (const int& a, const int& b) const {
int* arr1 = (int*) a;
int* arr2 = (int*) b;
int diff = arr2[1] - arr1[1];
if (diff) {
return true;
} else if (diff == 0) {
int diff2 = arr2[2] - arr1[2];
if (diff2) {
return false;
}
}
return arr1[0] < arr2[0];
}
};
set<int[3],sort_set> data;
Can someone point me in the right direction?
You cannot have arrays as elements of containers. They're not assignable nor copyable.
Use std::array<int, 3> if you have C++11 avaliable, or define a custom class otherwise.

dynamic memory allocation with arrays in c++

I am trying to insert an int into an array that is in a class object, and I cannot figure out what I am doing wrong. The current state of my code never inserts the int into the array.
Basically what I am trying to do is when i call insert(int) it will check to to see if there is any room left in the array, and if there is it will add it, otherwise it would reallocate with 8 more spaces in the array.
here is some relevant class info
private:
unsigned Cap; // Current capacity of the set
unsigned Num; // Current count of items in the set
int * Pool; // Pointer to array holding the items
public:
// Return information about the set
//
bool is_empty() const { return Num == 0; }
unsigned size() const { return Num; }
unsigned capacity() const { return Cap; }
// Initialize the set to empty
//
Set()
{
Cap = Num = 0;
Pool = NULL;
}
here is the code i am working on
bool Set::insert(int X)
{
bool Flag = false;
if (Num == Cap)
{
//reallocate
const unsigned Inc = 8;
int * Temp = new int[Cap+Inc];
for (unsigned J=0;J<Num;J++)
{
Temp[J] = Pool[J];
}
delete [] Pool;
Pool = Temp;
Cap = Cap+Inc;
}
if(Num < Cap)
{
Pool[Num+1] = X;
Flag = true;
}
return Flag;
}
Your insert function never updates Num. Try Pool[Num++] = X; or something like that.
You probably want to increment the number of element but only after copying the new element in: the first element should have index 0. Basically, your insert() function should look something like this:
bool Set::insert(int X)
{
if (Num == Cap)
{
const unsigned Inc(std::max(8, 2 * Cap));
std::unique_ptr<int[]> Temp(new int[Cap+Inc]);
std::copy(Pool.get(), Pool.get() + Num, Temp.get());
Pool.swap(Temp);
Cap += Inc;
}
Pool[Num] = X;
++Num;
return true;
}
Of course, this assumes that Pool is reasonably declared as std::unique_ptr<int[]> (or something with similar functionality which is easy to write if necessary). The reason to use std::unique_ptr<int[]> rather than raw pointers is that they automatically clean up resources when they are destroyed. Copying a sequence of ints won't throw an exception but if int get's replaced by a std::string or a template parameters there is potential to throw exceptions.

Removing int value in dynamic array and setting it to NULL

So my code is suppose to insert numbers into a dynamic array, add more capacity to the array if more is needed, remove numbers from the array and then make sure the only NULLS occur at the end of the array. It also tells the user how many numbers are in the array and what is the total size of the array. My problem is when I remove a number from the array, it sometimes prints out there is a number -33686019 in my array. This doesn't occur much, but I don't want it to occur at all.
#include <stdio.h>
#include <iostream>
int* gArray = NULL;
int gSize = 0;
int gCapacity = 0;
void Insert(int value);
void Remove(int value);
void Resize(int newCapacity);
void Print(void);
void main()
{
int input = 0;
while(input != 3)
{
printf(">=== Dynamic Array ===\n");
printf("What do you want to do?\n");
printf("1. Insert\n");
printf("2. Remove\n");
printf("3. Quit\n");
printf("Your choice: ");
scanf_s("%d", &input);
printf("\n\n");
int value = 0;
switch(input)
{
case 1:
{
printf("Enter a number: ");
scanf_s("%d", &value);
Insert(value);
Print();
break;
}
case 2:
{
printf("Enter number you wish to delete: ");
scanf_s("%d", &value);
Remove(value);
Print();
break;
}
case 3:
{
break;
}
default:
{
printf("Invalid selection\n");
}
}
}
}
void Insert(int value)
{
bool valueSet = false;
while(valueSet == false)
{
if(gArray == NULL)
{
Resize(1);
gArray[gSize] = value;
++gSize;
valueSet = true;
}
else if(gArray[gCapacity] == NULL)
{
gArray[gSize] = value;
++gSize;
valueSet = true;
}
else if(gArray[gCapacity] != NULL)
{
Resize((gCapacity + 1));
gArray[gSize] = value;
++gSize;
valueSet = true;
}
}
}
void Resize(int newCapacity)
{
int* tempArray = new int[newCapacity];
std::copy(gArray, gArray+(newCapacity-1), tempArray);
gArray = new int[newCapacity];
std::copy (tempArray, tempArray+(newCapacity-1), gArray);
gCapacity = newCapacity;
}
void Remove(int value)
{
for(int i = 0; i < gCapacity; ++i)
{
if(gArray[i] == value)
{
gArray[i] = NULL;
--gSize;
}
}
for(int i = 0; i < gCapacity; ++i)
{
if(gArray[i] == NULL)
{
gArray[i] = gArray[(i + 1)];
gArray[(i + 1)] = NULL;
}
}
}
void Print(void)
{
printf("Array contains: ");
for(int i = 0; i < gCapacity; ++i)
{
if(gArray[i] != NULL)
{
printf("%d, ", gArray[i]);
}
}
printf("size = %d, capacity = %d\n", gSize, gCapacity);
}
An option, since you are using the c++ standard library would be to remove all your code, and use std::list and its insert and remove methods. If you require the data to be in a dynamic array, then use std::vector and the erase remove idiom for removal.
I have to point out that, since your question is "Removing int value in dynamic array and setting it to NULL", that setting an int to NULL is essentially setting it to the value 0, since NULL tends to be a define for 0. So if your list were to contain zeroes, this setting to NULL and checking for equality with NULL would completely break the logic of your algorithm. C++11 has nullptr, an actual null type that cannot be assigned to an int, to deal with this kind of problem.
The concrete problem is that you don't initialize the new array (resp. tempArray) in your Resize function.
When calling
int* tempArray = new int[newCapacity];
the array can contain arbitrary values. Only newCapacity-1 values are copied from the old array, so the last value is undefined. It might be 0 but haven't to be. Use
std::fill(tempArray, tempArray+newCapacity, 0);
to initialize your array with zero.
Apart from that, there are a few other problems:
You don't delete the old array before allocating a new one. Use delete[] gArray for that. Also tempArrayisn't deleted!
You don't need to copy the values twice. Just to a gArray = tempArray (after deleting the old gArray, see above)
You assume that newCapacity is just larger by one than gCapacity (you copy newCapacity-1 values from the old array). It would be better to copy gCapacity values instead.
Dynamic arrays which only grow by one are inefficient, since adding a value takes linear time (you have to copy all the old values when inserting a single one). Usually, you double the size of the array every time you run out of space, this gives constant insertion time in average.
NULL is normally used only for pointers. For ints it is equal to zero which means, you cannot store 0 in your array (given your requirements)
In production code, I'd strongly recommend using std::vector instead of any home-grown solution.
EDIT
See #StackUnderflows answer for what is probably the real cause of the error. If you run in Debug mode, some compilers will automatically initialize the array for you, which might be the ccase here.
The gArray[i]=gArray[i+1] line in your Remove function is definitely wrong on the other hand, since it accesses a value which is beyond the limits of the array.
The problem occurs on the last iteration in the second loop of Remove when you do gArray[i] = gArray[i + 1]. On the last iteration, gArray[i + 1] is actually one past the end of your array, so you are now in undefined behavior territory. You are assigning this undefined value to the last element gArray[i].
I suggest using std::vector<int> instead. It manipulates an array under the hood which grows/resizes for you as you add more elements.