I am a beginner in C++. I typed a simple code to sort an integer array, but I couldn't figure out how to handle same elements like if I enter 1,12,3,5,11,3
output is given as 1,3,3,5,11,12 but I want the output to be 1,3,5,11,12.
What should I add further in the loop I've coded?
for(int i=0;i<len;i++)
{
for(int j=i+1;j<len;j++)
{
if(array[i]>array[j])
{
swap = array[i];
array[i] = array[j];
array[j] = swap;
}
}
}
If you really want to write it by yourself, do as they told you in comments.
If you just want to have a sorted list without duplicates, use std::set and insert all your numbers inside. You will get a sorted, unique list of ints.
It may be easier for you to understand this solution:
for(int i=0;i<len;i++)
{
for(int j=i+1;j<len;j++)
{
if(array[i]>array[j])
{
swap = array[i];
array[i] = array[j];
array[j] = swap;
}
}
}
cout<<array[0];
for(int i=1; i<len; ++i)
{
if(array[i] != array[i-1])
{
cout<<array[i];
}
}
Normal way :
Remove the duplicates from the array that you've sorted
int *start = array;
int *end = array+len;
int *res = start;
while (++start != end) {
if (!(*res == *start)) {
*(++res) = *start;
}
}
int new_len=++res -array;
Else why not simply use STL ?
std::sort(array,array+len);
int *res=std::unique(array,array+len);
int new_len=res -array;
Related
I'm trying to do a method where I have to delete a number from a vector of integers, and that number is passed as a parameter. The problem that I'm having right now is that when I try to delete the same number in consecutive positions, only one of them is deleted.
For example:
vector = (1, 2, 2, 3, 4, 5) and I want to remove the number "2", the result will be:
vector = (1, 2, 3, 4, 5)
But if the number is not in consecutive positions, the method works fine:
vector = (1, 2, 3, 2, 4, 5) ---> remove "2"
vector = (1, 3, 4, 5)
The code that I have is this:
void deleteNumber(int n, vector<int> &numbers)
{
bool hasEntered = false;
int counter = 0;
vector<int> deletedNumbers;
for(unsigned i = 0; i < numbers.size(); i++)
{
if(numbers[i] != n)
{
counter++;
}
else
{
counter = 0;
int counter2 = 0;
bool deleted = false;
for(unsigned j = 0; j < deletedNumbers.size() && deleted == false; j++) // Check if a number has been deleted before
{
if(deletedNumbers[j] != n)
{
counter2++;
}
else
{
deleted = true;
counter2 = 0;
}
}
if(counter2 == (int) deletedNumbers.size()) // Remove the number if it hasn't been removed
{
deletedNumbers.push_back(n);
for(unsigned k = 0; k<numbers.size(); k++)
{
if(numbers[k] == n)
numbers.erase(numbers.begin()+k);
}
counter2 = 0;
hasEntered = true;
}
}
}
}
I think that the error could be in the condition of the last for, where I finally remove the number.
The counters are used in order to determine if an element has been found or not. And also the method has to check if the item has been removed before.
If you don't understand something, please ask me.
Thanks in advance :)
you could try something like this:
void deleteNumber(int n, vector<int> &numbers)
{
vector<int>numbers_without_n;
for(unsigned i = 0; i < numbers.size(); i++)
if(numbers[i] != n)
numbers_without_n.push_back(numbers[i]);
numbers = numbers_without_n;
}
Your code looks like too complicated, thus it can contain many bugs.
This would delete all instances of n; O(numbers.size()):
void deleteNumber(int n, vector<int> &numbers) {
int i = 0;
for (int j = 0; j < numbers.size(); ++j) {
if (numbers[j] != n) numbers[i++] = numbers[j];
}
numbers.resize(i);
}
This would delete the first instance of n in each run; O(numbers.size()):
void deleteNumber(int n, vector<int> &numbers) {
int i = 0;
for (int j = 0; j < numbers.size();) {
if (numbers[j] == n) {
for (++j; j < numbers.size() && numbers[j] == n; ++j) {
numbers[i++] = numbers[j];
}
} else {
numbers[i++] = numbers[j++];
}
}
numbers.resize(i);
}
This would delete the first instance of n; O(numbers.size()):
void deleteNumber(int n, vector<int> &numbers) {
int i = 0;
for (int j = 0; j < numbers.size(); ++j) {
if (numbers[j] == n) {
for (++j; j < numbers.size(); ++j) {
numbers[i++] = numbers[j];
}
break;
}
numbers[i++] = numbers[j];
}
numbers.resize(i);
}
Pick whichever you need.
Please note that other answers, such as luk32's answer contain simpler code (using more STL) for deleting the first instance of n.
If you want to find and fix the bug in your code, I recommend that you try to find a very short input vector for which it fails, and then single-step through it in a debugger.
You don't need to have a loop inside the loop. The easiest way to handle the delete is to delete one item at a time and realize that this will mean you don't want to increment i when you have deleted an item. The easiest way to cancel the increment of i in the for loop is to decrement it first using --i. So you loop becomes
Check if the item matches the number
If so, delete the item and decrement i
Use std::remove and vector::erase
#include <algorithm>
void deleteNumber(int n, vector<int>& numbers)
{
numbers.erase(std::remove(numbers.begin(), numbers.end(), n), numbers.end());
}
First, I'm not sure what counter and counter2 are used for - if they're just being used to determine if you've iterated to the end of the vector without finding an element, you don't need them.
For the purpose of 'check if a number has been deleted', you just need a single boolean variable at the very top of the method, i.e. not inside the scope of the for loop.
I believe the following:
if(counter2 == (int) deletedNumbers.size()) // Remove the numbers if it hasn't been removed
can be replaced with if (!deleted).
So, here's a 'fixed' version while trying to stay as close to your existing logic as possible based on your code comments. This may not be the most efficient/elegant implementation however, I believe I have seen some other answers that use algorithms from the STL library to achieve the same thing.
void deleteNumber(int n, vector<int> &numbers)
{
bool deleted = false;
for(unsigned i = 0; i < numbers.size(); i++)
{
if (numbers[i] == n) // If we've found an instance of the number we're trying to delete
{
if (!deleted) // Check if an instance has already been deleted
{
numbers.erase(numbers.begin() + i); // Remove the number
deleted = true; // Flag that we have deleted an instance of the number
}
}
}
}
Alternately, instead of using a flag for 'deleted' to prevent deleting numbers after the first instance, you could optimize by just returning after you delete the first instance - that will prevent the rest of the loop from executing.
Ok, since apparently std::vector::erase does exists I would use standard c++ features:
void deleteNumber(int n, vector<int> &numbers) {
auto it = find(std::begin(numbers), std::end(numbers), n);
if(it != numbers.end()) numbers.erase(it);
}
EDIT: Forgot that end() is not a valid argument for erase.
I need to make a program that will accept a input file of numbers(integer.txt) which will be sorted one number per line, into a vector, then use a selection sort algorithm to sort the numbers in descending order and write them to the output file (sorted.txt). I'm quite sure something is wrong in my selectionSort() function that is causing the loop not to get the right values, because after tested with cout I get vastly improper output. I'm sure it's a beginning programmer's goof.
vector<string> getNumbers()
{
vector<string> numberList;
ifstream inputFile ("integer.txt");
string pushToVector;
while (inputFile >> pushToVector)
{
numberList.push_back(pushToVector);
}
return numberList;
}
vector<string> selectionSort()
{
vector<string> showNumbers = getNumbers();
int vectorMax = showNumbers.size();
int vectorRange = (showNumbers.size() - 1);
int i, j, iMin;
for (j = 0; j < vectorMax; j++)
{
iMin = j;
for( i = j; i < vectorMax; i++)
{
if(showNumbers[i] < showNumbers[iMin])
{
iMin = i;
}
}
if (iMin != j)
{
showNumbers[j] = showNumbers [iMin];
}
}
return showNumbers;
}
void vectorToFile()
{
vector<string> sortedVector = selectionSort();
int vectorSize = sortedVector.size();
ofstream writeTo;
writeTo.open("sorted.txt");
int i = 0;
while (writeTo.is_open())
{
while (i < vectorSize)
{
writeTo << sortedVector[i] << endl;
i += 1;
}
writeTo.close();
}
return;
}
int main()
{
vectorToFile();
}
vectorRange defined but not used.
In your selectionSort(), the only command that changes the vector is:
showNumbers[j] = showNumbers [iMin];
Every time control reaches that line, you overwrite an element of the vector.
You must learn to swap two values, before you even think about sorting a vector.
Also, your functions are over-coupled. If all you want to fix is selectionSort, then you should be able to post that plus a main that calls it with some test data and displays the result, but no, your functions all call each other. Learn to decouple.
Also your variable names are awful.
This is my implementation , i have a txt file where the animals are randomly assign. i want to order them and insert it into a list.
void SortedList::insert(std::string x){
int insertPoint=0;
if(top==n){
n = 2 * n;
string* temp = arr;
arr = new string[n];
for (int i = 0; i < top; i++){
arr[i] = temp[i];
}
delete[] temp;
}
arr[top]=x;
LinearOrdering();
top++;
}
and
void SortedList::LinearOrdering(){
for(int i=0; i < top ; i++){
if (arr[i] > arr[ i + 1]) {
swap (arr[i], arr[i+1]);
}
}
}
this is my result
aardvark
baboon
cougar
gorilla
lion
mouse
ocelot
gerbil
orangutan
hamster
panther
elephant
rat
rhinoceros
tiger
hippopotamus
zebra
what wrong with my code that make it partially ordered.
It looks like you're trying to bubble-sort the list. You will have to loop more than once to make it work.
This answer assumes you're doing this for educational purposes. Otherwise, as StilesCrisis suggests, use std::sort() and also you might prefer std::vector<std::string> instead of a string*.
LinearOrdering does not sort the data, it just swaps some elements around.
Save yourself some trouble and call std::sort.
problem is with your linearordering function
oid SortedList::LinearOrdering(){
for(int i=0; i < top ; i++){
if (arr[i] > arr[top]) {
swap (arr[i], arr[top]);
break;
}
}
}
So what I have to do is insert certain values from one array to another one directly sorted without having to sort them later using BubbleSort or QuickSort or any other method. I can't think of a way to do this... I have to insert them from the biggest value to the smallest one. Here's what I have until now:
void palindroame (int x[100], int y[100]) {
int i=0, j, k=0, aux;
while (x[i]!=0) {
k++; i++;
}
i=0;
for (i=0; i<=k-1; i++) y[i]=0;
for (i=0; i<=k-1; i++) {
if (palindrom(x[i])!=0 && palindrom(x[i+1])!=0)
if (x[i]<x[i+1]) {
aux=x[i+1]; x[i+1]=x[i]; x[i]=aux;
}
} //wrong
for (i=0; i<=k-1; i++) {
if (palindrom(x[i])) y[i]=x[i];
} //wrong
}
Thanks in advance!
The algorithm you need is selection sort, you can use this to sort and copy at the same time.
You can have a look at priority queues:
http://www.cplusplus.com/reference/queue/priority_queue/
Heres an example of a selection sort i have done recently (in which a is a vector)
should give you enough to go on hope it helps, ask questions if u like
for (unsigned int i = 0; i < a.size()-1; i++)
{
int min = i;
for(unsigned int j = i +1; j < a.size(); j++)
{
// If new minimum is found then stores this as the new minimum
if(a[j] < a[min])
{
min = j;
}
}
// Stores the values in the array in ascending order
if (min != i)
{
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
// Returns the array in ascending order
return a;
Edit: just to clarify this is working on a vector that already has values in it in case that wasnt clear but example with code comments i think is enough to help you IMO
I'm using bubble sort to sort numbers in an array in order from lowest to highest. But there are some numbers which are the same, but I don't need them to be printed twice. So how do I check whether it was already printed and not to repeat the action?
The Bubble sort:
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
if(m[i]>m[j]){
temp=m[i];
m[i]=m[j];
m[j]=temp;
}
}
}
Since number are already sorted when you are printing it, you can store the last printed number and compare against this before printing.
Something like:
std::cout << m[0] << std::endl;
int last_print = m[0];
for(int i = 1; i < n; ++i)
{
if(m[i] != last_print)
{
std::cout << m[i] << std::endl;
last_print = m[i];
}
}
filter duplicate out when printing (assuming m being int[])
int last = 0;
for(int i=0;i<n;i++){
int num = m[i];
if (i == 0 || last != num) {
// print num;
}
last = num;
}
or this way if you don't like too much vars
for(int i=0;i<n;i++){
if (i == 0 || m[i - 1] != [i]) {
// print m[i];
}
}
Alternatively you could remove duplicates on sort
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;){
if (m[i]==m[j]) { // remove
m [j] = m [n - 1]; // replace with last
n --; // cut last
} else {
if(m[i]>m[j]){
temp=m[i];
m[i]=m[j];
m[j]=temp;
}
j ++;
}
}
}
You can add the number to a std::set as soon as you print it, and check all numbers if they are in the set before printing them.
EDIT: I missed the restriction that the numbers are sorted. In that case, a set is overkill and less efficient than just keeping track of the last number printed, and only printing numbers that are different from it afterwards.