Introduction
Implement a class named static linked list which is based on an fiexed length array storage and figure out the logic inside this.
Related knowledge:(click on the following wedsite)
1、https://en.wikipedia.org/wiki/Linked_list#Linked_lists_using_arrays_of_nodes
2、What’s more, if your code has the request of Google style ,you can click on the website http://clang.llvm.org/docs/ClangFormat.html to learn how to repair automatically.
Ok, now let us to learn how to code a static linked list.Here I have give the main.cpp and list.hpp(it would be a little long), and what we to do is to finish the list.cpp.
/* main.cpp*/
#include <iostream>
#include <string>
#include "list.hpp"
using std::cin;
using std::cout;
using std::endl;
using std::string;
int main() {
list li;
int n;
cin >> n;
for (int i = 0, data, pos; i < n; i++) {
cin >> pos >> data;
li.insert(pos, data);
}
cout << li.toString() << " size: " << li.size() << endl;
list li2(li);
list li3;
li = li3 = li2 = li;
cout << li.toString() << " size: " << li.size() << endl;
cout << li2.toString() << " size: " << li2.size() << endl;
cout << li3.toString() << " size: " << li3.size() << endl;
int m;
cin >> m;
for (int i = 0, pos; i < m; i++) {
cin >> pos;
li.erase(pos);
}
for (int i = 0, temp; i < m; i++) {
cin >> temp;
li.insert(0, temp);
}
cout << li.toString() << endl;
cout << li.sort().toString() << endl;
cout << li2.sort().toString() << endl;
cout << li3.sort().toString() << endl;
return 0;
}
/*list.hpp*/
#ifndef LIST_H_
#define LIST_H_
#include <string>
#define MAX_STORAGE 1000
class list{
typedef int data_type;
typedef int pointer;
typedef unsigned int size_type;
static const pointer nullpointer = -1;
typedef struct node {
data_type data;
pointer next;
node(const node &another) {
this->operator=(another);
}
node& operator=(const node &another) {
this->data = another.data;
this->next = another.next;
}
node(data_type data = 0, pointer next = nullpointer) : data(data), next(next) {}
} node;
node storage[MAX_STORAGE];
size_type _size;
pointer head;
pointer empty_head;
public:
list();
list(const list& another);
list& operator=(const list&);
~list();
// Capacity
bool empty(void) const;
size_type size(void) const;
// output
// list: [1,2,3,4,5]
// output: 1->2->3->4->5->NULL
std::string toString(void) const;
void insert(int position, const int& data);
void erase(int position);
void clear(void);
list& sort(void);
};
#endif // !LIST_H_
/*list.cpp*/
#include "list.hpp"
#include <string>
#include <sstream>
#include <assert.h>
list::list() { this->clear(); }
list::list(const list& another) { *(this) = another; }
list::~list() {}
list& list::operator=(const list& another) {
this->clear();
for (int i = 0; i < MAX_STORAGE; i++) {
storage[i] = another.storage[i];
}
this->head = another.head;
this->empty_head = another.empty_head;
this->_size = another._size;
return *(this);
}
bool list::empty(void) const { return this->_size == 0; }
list::size_type list::size(void) const { return this->_size; }
std::string list::toString(void) const {
pointer p = this->head;
std::string ret;
while (p != nullpointer) {
std::stringstream ss;
ss << this->storage[p].data;
ret += ss.str();
ret += "->";
p = this->storage[p].next;
}
ret += "NULL";
return ret;
}
void list::insert(int position, const int& data) {
if (position >= 0 && position <= this->_size) {
if (this->_size + 1 <= MAX_STORAGE) {
pointer freeNode = empty_head;
empty_head = storage[empty_head].next;
storage[freeNode].data = data;
if (position == 0) {
storage[freeNode].next = head;
head = freeNode;
} else {
pointer p = head;
for (int i = 0; i < position - 1; i++) {
p = storage[p].next;
}
storage[freeNode].next = storage[p].next;
storage[p].next = freeNode;
}
this->_size++;
}
}
}
void list::erase(int position) {
if (position >= 0 && position < this->_size) {
if (position == 0) {
pointer temp = head;
head = storage[head].next;
storage[temp].next = empty_head;
empty_head = temp;
} else {
pointer p = head;
for (int i = 0; i < position - 1; i++) {
p = storage[p].next;
}
pointer temp = storage[p].next;
assert(storage[p].next != nullpointer);
storage[p].next = storage[storage[p].next].next;
storage[temp].next = empty_head;
empty_head = temp;
}
this->_size--;
}
}
void list::clear(void) {
this->head = nullpointer;
this->_size = 0;
this->empty_head = 0;
for (int i = 0; i < MAX_STORAGE - 1; i++) {
storage[i].next = i + 1;
}
storage[MAX_STORAGE - 1].next = nullpointer;
}
list& list::sort(void) {
if (this->head != nullpointer && this->storage[head].next != nullpointer) {
pointer slow = head;
pointer fast = storage[head].next;
while (fast != nullpointer) {
if (storage[fast].data >= storage[slow].data) {
fast = storage[fast].next;
slow = storage[slow].next;
} else {
pointer pre = this->head;
if (storage[head].data > storage[fast].data) {
storage[slow].next = storage[fast].next;
storage[fast].next = this->head;
this->head = fast;
} else {
while (storage[storage[pre].next].data <= storage[fast].data) {
pre = storage[pre].next;
}
storage[slow].next = storage[fast].next;
storage[fast].next = storage[pre].next;
storage[pre].next = fast;
}
fast = storage[slow].next;
}
}
}
return *(this);
}
Compile error:
1、error: ‘string’ does not name a type
We just add this :
using namespace std;
2、error: ‘size_type’ does not name a type
we should take the type list::
before the size_type
.
3、In my wrong code,there are concepts about c++ class that I am not clear.Thus I get many Compile errors.
First, typedef int pointer;
means pointer
is a type of int
,not a pointer. So I shouldn’t use empty_head->next
to get the next data, and I can use the array to get.
Second, node* p
means p is a pointer which its type is node
, in here pointer
is a type of int
,when their type is distinct, if we convert one to another, then will occur Compile error,like this error: invalid conversion from ‘list::pointer’ to ‘list::node*’
For example:
error: base operand of ‘->’ is not a pointer
error: NULL used in arithmetic
error: invalid conversion from ‘list::pointer’ to ‘list::node*’
4、About the Header files!!! If you had use stringstream
to convert sth. to string
, you must remmember to add the include #include<sstream>
5、If you want to get theData of next location without pointer,you should code like this storage[storage[l].next].data
instead of storage[l].next->data
or storage[l].next.data
Error answer:
[I] [Test input]
+---------------------------------------------------------------------
|5
|0 6 0 7 0 8 0 9 0 3
|2
|3 1
|5 6
+---------------------------------------------------------------------
[Incorrect stdout output]
Your program's stdout output:
+---------------------------------------------------------------------
001 |3->NULL size: 5
002 |3->NULL size: 5
003 |3->NULL size: 5
004 |3->NULL size: 5
005 |6->NULL
006 |6->NULL
007 |3->NULL
008 |3->NULL
009 |
+---------------------------------------------------------------------
Standard answer's stdout output:
+---------------------------------------------------------------------
001 |3->9->8->7->6->NULL size: 5
002 |3->9->8->7->6->NULL size: 5
003 |3->9->8->7->6->NULL size: 5
004 |3->9->8->7->6->NULL size: 5
005 |6->5->3->8->6->NULL
006 |3->5->6->6->8->NULL
007 |3->6->7->8->9->NULL
008 |3->6->7->8->9->NULL
009 |
+---------------------------------------------------------------------
Solution: As we know, we want to use array to simulate the list, the location in the array acts for the pointers in the list.Thus in the constructor function we should add the following code:
for (int i = 0; i < MAX_STORAGE - 1; i++) {
storage[i].next = i + 1;
}
storage[MAX_STORAGE - 1].next = nullpointer;
[II][Test input]
+---------------------------------------------------------------------
|5
|0 0 0 1 0 2 0 3 0 4
|4
|0 1 2 3
|0 1 2 3
+---------------------------------------------------------------------
[Incorrect stdout output]
Your program's stdout output:
+---------------------------------------------------------------------
001 |4->43->432->4321->43210->NULL size: 5
002 |4->43->432->4321->43210->NULL size: 5
003 |4->43->432->4321->43210->NULL size: 5
004 |4->43->432->4321->43210->NULL size: 5
005 |3->32->321->3210->32103->321031->NULL
006 |1->13->132->1321->13210->NULL
007 |4->43->432->4321->43210->NULL
008 |4->43->432->4321->43210->NULL
009 |
+---------------------------------------------------------------------
Standard answer's stdout output:
+---------------------------------------------------------------------
001 |4->3->2->1->0->NULL size: 5
002 |4->3->2->1->0->NULL size: 5
003 |4->3->2->1->0->NULL size: 5
004 |4->3->2->1->0->NULL size: 5
005 |3->2->1->0->3->1->NULL
006 |0->1->1->2->3->3->NULL
007 |0->1->2->3->4->NULL
008 |0->1->2->3->4->NULL
009 |
+---------------------------------------------------------------------
The difference:
+---------------------------------------------------------------------
|1,8c1,8
|< 4->3->2->1->0->NULL size: 5
|< 4->3->2->1->0->NULL size: 5
|< 4->3->2->1->0->NULL size: 5
|< 4->3->2->1->0->NULL size: 5
|< 3->2->1->0->3->1->NULL
|< 0->1->1->2->3->3->NULL
|< 0->1->2->3->4->NULL
|< 0->1->2->3->4->NULL
|---
|> 4->43->432->4321->43210->NULL size: 5
|> 4->43->432->4321->43210->NULL size: 5
|> 4->43->432->4321->43210->NULL size: 5
|> 4->43->432->4321->43210->NULL size: 5
|> 3->32->321->3210->32103->321031->NULL
|> 1->13->132->1321->13210->NULL
|> 4->43->432->4321->43210->NULL
|> 4->43->432->4321->43210->NULL
|
+---------------------------------------------------------------------
Failed Test Case #1
[Test input]
+---------------------------------------------------------------------
|5
|0 6 0 7 0 8 0 9 0 3
|2
|3 1
|5 6
+---------------------------------------------------------------------
[Time limit for your program (1 sec) exceeded]
Failed Test Case #2
[Test input]
+---------------------------------------------------------------------
|5
|0 12 1 5 2 98 3 44 0 21
|3
|0 1 2
|5 6 7
+---------------------------------------------------------------------
[Time limit for your program (1 sec) exceeded]
Failed Test Case #3
[Test input]
+---------------------------------------------------------------------
|1
|2 3
|3
|1 2 3
|3 2 1
+---------------------------------------------------------------------
[Time limit for your program (1 sec) exceeded]
Failed Test Case #4
[Test input]
+---------------------------------------------------------------------
|0
|5
|1 2 3 4 5
|1 2 3 4 5
+---------------------------------------------------------------------
[Incorrect stdout output]
Your program's stdout output:
+---------------------------------------------------------------------
001 |NULL size: 0
002 |NULL size: 0
003 |NULL size: 0
004 |NULL size: 0
005 |5->54->543->5432->54321->NULL
006 |5->54->543->5432->54321->NULL
007 |NULL
008 |NULL
009 |
+---------------------------------------------------------------------
Standard answer's stdout output:
+---------------------------------------------------------------------
001 |NULL size: 0
002 |NULL size: 0
003 |NULL size: 0
004 |NULL size: 0
005 |5->4->3->2->1->NULL
006 |1->2->3->4->5->NULL
007 |NULL
008 |NULL
009 |
+---------------------------------------------------------------------
The difference:
+---------------------------------------------------------------------
|5,6c5,6
|< 5->4->3->2->1->NULL
|< 1->2->3->4->5->NULL
|---
|> 5->54->543->5432->54321->NULL
|> 5->54->543->5432->54321->NULL
|
+---------------------------------------------------------------------
Solution: In the toString
function ,put the stringstream s;
into the while
instead of out of while
; Notice the sort
is from small to large; clear()
and the construct function must be careful;
Time limit is the most difficult problems for me,now I still can’t solve if you know how to solve it ,please tell me!!!
My code:
#include<iostream>
#include "list.hpp"
#include<string>
#include<sstream>
using namespace std;
#define MAX_STORAGE 1000
list::list() {
_size = 0;
head = nullpointer;
empty_head = 0;
for (int i = 0; i < 999; i++) {
storage[i].next = i+1;
}
storage[999].next = nullpointer;
}
list::list(const list& another) {
head = nullpointer;
_size = 0;
*this = another;
}
list& list::operator=(const list&s) {
if (this != &s) {
clear();
empty_head = s.empty_head;
head = s.head;
this->_size = s._size;
for (int i = 0; i < 1000; i++) {
storage[i] = s.storage[i];
}
}
return *this;
}
list::~list() {
this->clear();
}
// Capacity
bool list::empty(void) const {
return this->_size == 0;
}
list::size_type list::size(void) const {
return this->_size;
}
// output
// list: [1,2,3,4,5]
// output: 1->2->3->4->5->NULL
string list::toString(void) const {
pointer pos = this->head;
string r;
while (pos != nullpointer) {
stringstream s;
s << storage[pos].data;
r += s.str();
r += "->";
pos = storage[pos].next;
}
r += "NULL";
return r;
}
void list::insert(int p, const int& data) {
if (p > this->_size || p < 0) {
return;
}
pointer t = empty_head;
empty_head = storage[empty_head].next;
storage[t].data = data;
if (p == 0) {
storage[t].next = head;
head = t;
} else {
pointer p = head;
int c = 0;
while (c != p-1) {
p = storage[p].next;
c++;
}
storage[t].next = storage[p].next;
storage[p].next = t;
}
_size++;
}
void list::erase(int p) {
if (p >= _size || p < 0) {
return;
} else if (p == 0) {
pointer t = head;
head = storage[head].next;
storage[t].next = empty_head;
empty_head = t;
} else {
pointer o = head;
int c = 0;
while (c != p - 1) {
c++;
o = storage[o].next;
}
pointer t = storage[o].next;
storage[o].next = storage[t].next;
storage[t].data = 0;
pointer h = empty_head;
empty_head = t;
storage[empty_head].next = h;
}
_size--;
}
void list::clear(void) {
pointer p;
pointer q;
while (head != nullpointer) {
p = head;
storage[p].data = 0;
q = empty_head;
head = storage[head].next;
empty_head = p;
storage[empty_head].next = q;
}
_size = 0;
}
list& list::sort(void) {
if (head == nullpointer || storage[head].next == nullpointer) {
return *this;
}
pointer t = head;
pointer p = storage[head].next;
while (p != nullpointer) {
if (storage[p].data >= storage[t].data) {
p = storage[p].next;
t = storage[t].next;
} else {
pointer l = head;
if (storage[head].data > storage[p].data) {
storage[t].next = storage[p].next;
storage[p].next = head;
head = p;
} else {
while (storage[storage[l].next].data <= storage[p].data) {
l = storage[l].next;
}
storage[t].next = storage[p].next;
storage[p].next = storage[l].next;
storage[l].next = p;
}
p = storage[t].next;
}
}
return *this;
}
My code's error:
[Test input]
+---------------------------------------------------------------------
|5
|0 12 1 5 2 98 3 44 0 21
|3
|0 1 2
|5 6 7
+---------------------------------------------------------------------
[Time limit for your program (1 sec) exceeded]
PS:
/*list.cpp*/
//This the first wrong code I wrote:
#include<iostream>
#include "list.hpp"
#include<string>
#define MAX_STORAGE 1000
list::list() {
_size = 0;
head = -1;
empty_head = 0;
}
list::list(const list& another) {
*this = another;
}
list& list::operator=(const list&s) {
if (this != &s) {
clear();
empty_head = s.empty_head;
head = s.head;
this->_size = s._size;
for (int i = 0; i < 1000; i++) {
storage[i] = s.storage[i];
}
}
return *this;
}
list::~list() {
this->clear();
}
// Capacity
bool list::empty(void) const {
return this->_size == 0;
}
list::size_type list::size(void) const {
return this->_size;
}
// output
// list: [1,2,3,4,5]
// output: 1->2->3->4->5->NULL
string list::toString(void) const {
node* pos = this->head;
string r;
stringstream s;
while (pos != NULL) {
s << pos->data;
string t;
s >> t;
r += t + "->";
s.clear();
pos += pos->next;
}
r += "NULL";
return r;
}
void list::insert(int p, const int& data) {
if (p > this->_size || p < 0) {
return;
} else if (p == 0) {
node* t = new node(data, head);
head = t;
} else {
node* p = head;
int c = 1;
while (c != p) {
p = p->next;
c++;
}
node* t = new node(data, p->next);
p->next = t;
}
_size++;
}
void list::erase(int p) {
if (p >= _size || p < 0) {
return;
} else if (p == 0) {
node* t = head;
head = head->next;
delete t;
} else {
node* o = head;
int c = 0;
while (c != p - 1) {
c++;
o = o->next;
}
node* t = o->next;
o->next = t->next;
delete t;
}
_size--;
}
void list::clear(void) {
if (head != NULL) {
empty_head = head;
while (empty_head != NULL) {
node* t = empty_head;
empty_head = empty_head->next;
delete t;
}
head = NULL;
empty_head = NULL;
}
_size = 0;
}
list& list::sort(void) {
if (head == NULL || head->next == NULL) {
return;
}
node* t = head;
node* p = head->next;
while (p != NULL) {
if (p->data <= t->data) {
p = p->next;
t = t->next;
} else {
node *l = head;
if (head->data < p->data) {
t->next = p->next;
p->next = head;
head = p;
} else {
while (l->next->data >= p->data) {
l = l->next;
}
t->next = p->next;
p->next = l->next;
l->next = p;
}
p = t->next;
}
}
return *this;
}