# Data structure note 2: linear table

Posted by richie19rich77 on Sat, 30 Oct 2021 10:45:12 +0200

## Basic concepts

1. A linear table is a finite sequence of n data elements. The elements in the same linear table must have similarity
2. Do not care about the specific data between elements, but about the relationship between elements
3. Linear table operations: create, judge whether it is empty, determine the length, find, delete and insert

## Array description (sequential storage)

1. C + + class definition

```template<class T>
class LinearList{
public:
LinearList(int MaxListSize=10); //Constructor
~LinearList(){delete[] element;) //Destructor
bool IsEmpty() const{return length==0;}
int Length() const(return length;)
bool Find(int k,T& x) const; //Reference to return the k-th element of the list
int Search(const T& x) const; //Returns the position of x (no duplicate elements)
LinearList<T> Delete(int k,T& x); //Delete the k-th element and save it in x
LinearList<T>& Insert(int k, const T& x); //Insert x after the k th element
void Output(ostream& out) const;
private:
int length;
int MaxSize; //Fixed part, ignore
T *element; //One dimensional dynamic array
}```
2. C + + implementation: create and release
```template<class T>
LinearList<T>::LinearList(int MaxListSize){
MaxSize=MaxListSize;
element=new T[MaxSize]; //Time complexity: constant level
length=0;
}

~Linearlist(){ //Time complexity: constant level
delete[] element;
}```
3. lookup

```template<class T>
bool LinearList<T>::Find(int k,T& x) const{
if(k<1||k>length)
return false;
x=element[k-1];
return true;
} //Time complexity: O(1)

template<class T>
bool LinearList<T>::Search(int k,T& x) const{
for(int i=0;i<length;i++)
if(element[i]==x)
return ++i;
return 0;
} //Time complexity: O(length)```
4. delete

```template<class T>
LinearList<T>& LinearList<T>::Delete(int k,T& x){
if(Find(k,x)){ //If the element can be found
for(int i=k;i<length;i++)
element[i-1]=element[i]; //Move the following elements forward one space
length--;
return *this;
} //Time complexity: O(length-k)
else
throw OutOfBounds(); //Out of bounds, exception
return *this;
}

template<class T>
LinearList<T>& LinearList<T>::Insert(int k,const T& x){
if(k<0||k>length)
throw OutOfBounds(); //k illegal
if(length==MaxSize)
throw NoMem(); //Table space is full and cannot be inserted again
for(int i=length-1;i>=k;i--) //General situation
element[i+1]=element[i];
element[k]=x;
length++;
return *this;
//Problem: the element needs to be moved, and it is easy to overflow
} //Time complexity: O(length-k)```
5. output
```template<class T>
void LinearList<T>::Output(ostream& out) const{
for (int i=0;i<length;i++)
out<<element[i]<<" ";
}

template<class T>
ostream& operator<<(ostream& out, const LinearList<T>& x){
x.Output(out);
return out;
}```
6. Evaluation: low space efficiency

```template<class T>
class ChainNode{
friend Chain<T>; //Declared friend class
friend ChainIterator<T>;
private:
T data; //Stored data
ChainNode<T> *link; //Point to next node
}```
```template<class T>
class Chain{
friend ChainIterator<T>;
public:
Chain(){first=0;} //Create an empty linked list
~Chain();
bool IsEnmpty()const {return first==0;}
int Length() const;
bool Find(int k,T& x) const;
int Search(const T& x) const;
Chain<T>& Delete(int k,T& x);
Chain<T>& Insert(int k,const T& x);
void Output(ostream& out) const;
private:
ChainNode<T> *first; //First pointer
}

template<class T>
Chain<T>::~Chain(){
ChainNode<T> *next; //A temporary variable that controls the pointer
while(first){ //The next node exists
delete first;
first=next;
}
} //Time complexity: O(n)

template<class T>
int Chain<T>::Length()const{
ChainNode<T> *current=first;
int len=0;
while(current){
len++;
}
return len;
} //Time complexity: O(n)

template<class T>
bool Chain<T>::Find(int k, T& x) const{
if(k<1)
return false;
ChainNode<T> *current=first;
int index=1;
while(index<k&&current){
index++;
}
if(current){ //If the pointer points to something real
x=current->data;
return true;
}
return false;
} //Time complexity: O(k)

template<class T>
bool Chain<T>::Search(const T& x) const{
ChainNode<T> *current=first;
int index=1; //Used to record where x is
while(current&&current->data!=x){ //If you haven't found x
index++;
}
if(current) //If the pointer points to something real
return index;
return 0;
} //Time complexity: O(n)

template<class T>
void Chain<T>::Output(ostream& out)const{
ChainNode<T> *current;
out << current->data << " ";
}

template <class T>
ostream& operator<<(ostream& out, const Chain<T>& x){
x.Output(out);
return out;
} //Time complexity: O(n)

template<class T>
Chain<T>&Chain<T>::Delete(int k, T& x){
if(k<1||first) //If k is illegal or the linked list is empty
throw OutOfBounds();
ChainNode<T> *p=first; //A temporary variable that eventually points to the k-th element
if(k==1) //If you want to delete the first element
else{ //If you want to delete the middle element
ChainNode<T> *q=first; //You want it to point to the previous element of the element you want to delete
for(int index=1;index<k-1&&q;index++)
throw OutOfBounds();
}
x=p->data;
delete p; //Release the memory space occupied by item k, but do not delete the data. It may be used elsewhere
return *this;
} //Time complexity: O(n)

template<class T>
Chain<T>&Chain<T>::Insert(int k, const T& x){
if(k<0) //If k is illegal
throw OutOfBounds();
ChainNode<T> *p=first; //A temporary variable that eventually points to the k-th element
for(int index=1;index<k&&p;index++)
if(k>0&&!p)
ChainNode<T> *y=new ChainNode<T>;
if(k){
}
else{ //When k=0, the chain header element is inserted
first=y; //Remember to update the header node
}
return *this;
}

template<class T>
void Chain<T>::Erase(){ //Delete all nodes of the linked list
ChainNode<T> *next;
while (first){
delete first;
first = next;
}
}

template<class T>
Chain<T>& Chain<T>::Append(const T& x){ //Add an element at the end of the linked list
ChainNode<T> *y;
y = new ChainNode<T>;
y->data = x;
if (first) {//If the linked list is not empty
last = y;
}
else //The linked list is empty
first = last = y;
return *this;
}```
3. Two improved forms
(1) Point the tail node to the head node
```template<class T>
bool Chain<T>::Search(const T& x) const{ //Optimization of Search function of leading node
int index=1; //Used to record where x is
first->data=x; //Save the value of x in an empty header node and set an termination condition
while(current->data!=x){ //If you haven't found x
index++;
}
}```
```template <class T>
class DoubleNode {
friend Double<T>;
private:
T data;
DoubleNode<T> *left, *right;
};

template<class T>
class Double {
public:
Double() {LeftEnd = RightEnd = 0;};
~Double();
int Length() const;
bool Find(int k, T& x) const;
int Search(const T& x) const;
Double<T>& Delete(int k, T& x);
Double<T>& Insert(int k, const T& x);
void Output(ostream& out) const;
private:
DoubleNode<T> *LeftEnd, *RightEnd; //* RightEnd can be omitted from the two-way circular linked list
};```

5. summary
(1) Spatial complexity
​​​​​​​           The formulaic space is all used to save the list data, while the linked list has additional space to save the link pointer
The linked list is dynamically allocated, the occupied space is proportional to the current linked list size, and the utilization rate is high; The formulation is static distribution, which can not predict the actual demand, resulting in waste or shortage
(2) Time complexity
​​​​​           The performance of inserting and deleting operations is better described by linked list, while the performance of random access is better described by formula

## Application of linear table

### bin sort

1. A lot of data is stored
2. Limited range of stored data
3. Sorting method realized by linked list
Delete each node (head node) of the linked list one by one
Put the deleted node into the appropriate box (insert the head position of the corresponding linked list)
Collect and link all boxes to generate a sorting linked list (adjacent boxes are connected from beginning to end)
```class Node {
friend ostream& operator<<(ostream&, const Node &);
friend void BinSort(Chain<Node>&, int);
public:
return (score != x.score);
}
private:
int score;
char *name;
};

out << x.score << ' ';
return out;
}

void BinSort(Chain<Node>& X,int range){ //Value range of element
int len=X.length();
Node x;
Chain<Node> *bin;
bin=new Chain<Node>[range+1];
for(int i=1;i<len;i++){
} //O(n)
for(int j=range;j>=0;j--) //Starting from the last box, insert the large data into the ordered linked list first, because each insertion is at the head, so the large elements will go to the back
while(!bin[j].IsEmpty()){ //If the box is not empty (it is already empty or has been taken)
} //O(n+range)
delete[] bin;
} //Time complexity: 2n+range

//Problem: there are many times of new and Delete in Delete and Insert, and this is required for each cycle```
```//update: avoid frequent calls to Delete and Insert

template<class T>
void Chain<T>::BinSort(int range){ //Sort the box as a member function of the linked list
int b;
ChainNode<T> **bottom, **top; //Initialize box
bottom=new ChainNode<T>* [range+1];
top=new ChainNode<T>* [range+1];
for(b=0;b<=range;b++)
bottom[b]=NULL;
b=first->data;
if(bottom[b]){ //If the box is not empty
top[b]=first;
}
else
bottom[b]=top[b]=first;
}
ChainNode<T> *y=0;
for(b=0;b<=range;b++)
if(bottom[b]){
if(y)
else
first=bottom[b];
y=top[b];
}
if(y)
delete[] bottom;
delete[] top;
} //Time complexity: n+2range```

# Assignment 2

``` //Splice the two linked lists alternately into a linked list
template <typename T>
class extendedChain{
struct node{
T data;
node *next;
};
public:
extendedChain(); //Constructor
void append(T t); //Splice the data at the end of the linked list
bool empty(); //Determine whether the linked list is empty
};

template <typename T>
extendedChain<T>::extendedChain(){
}

template <typename T>
void extendedChain<T>::append(T t){
node *p=new node;
p->data=t;
p->next=NULL;
return;
}
while(tail->next) //Find the location of the tail node
tail=tail->next;
tail->next=p; //Connect the new node to the back
}

template <typename T>
void extendedChain<T>::display(){
while(p){ //Sequential output
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}

template <typename T>
bool extendedChain<T>::empty(){
return false;
else
return true;
}

template <typename T>
}

template <typename T>
void meld(extendedChain<T> a,extendedChain<T> b){
extendedChain<T> c;
while(!a.empty()&&!b.empty()){ //When neither is empty
}
while(!b.empty()){ //Add all the remaining elements to c
}
while(!a.empty()){
}
c.display();
}

int main(){
extendedChain<int> a,b;
cout<<"Please input 7 integers in entended chain a!"<<endl;
int t;
for(int i=1;i<=7;i++){
cin>>t;
a.append(t);
}
cout<<"Please input 10 integers in entended chain b!"<<endl;
for(int i=1;i<=10;i++){
cin>>t;
b.append(t);
}
meld(a, b);
return 0;
}
```

### Split a linked list into two linked lists according to the index

```//Split a linked list into two lists according to the index
template <typename T>
class extendedChain{
struct node{
T data;
node *pre; //Bidirectional cycle
node *next;
};
public:
node *mark;
extendedChain();
void append(T t);
void display();
bool empty();
void split();
};

template <typename T>
extendedChain<T>::extendedChain(){
}

template <typename T>
void extendedChain<T>::append(T t){
node *p=new node;
p->data=t;
p->next=NULL;
return;
}
while(tail->next)
tail=tail->next;
tail->next=p;
p->pre=tail;
}

template <typename T>
void extendedChain<T>::display(){
while(p){
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}

template <typename T>
bool extendedChain<T>::empty(){
return false;
else
return true;
}

template <typename T>
p->pre=NULL;
}

template <typename T>
void extendedChain<T>::split(){

}

void split(extendedChain<int>c){ //Non member function method
extendedChain<int>a,b;
int index=1;
while(c.mark){
if(index%2==0) //Index is double
b.append(c.mark->data);
else //Index is single
a.append(c.mark->data);
c.mark=c.mark->next;
index++;
}
a.display();
b.display();
}

int main(){
extendedChain<int> c;
cout<<"Please input 10 integers in entended chain c!"<<endl;
int t;
for(int i=1;i<=10;i++){
cin>>t;
c.append(t);
}
split(c);
return 0;
}
```

Topics: data structure