Lists, Stacks, and Queues

Lists, Stacks, and Queues

Lists

Introduction

  • Each element has a data type (atomic or structure)
  • Empty list contains no elements
  • The length is the number of elements stored
  • The beginning of the list is called the head
  • The end of the list is called the tail
  • Types
    • Sorted lists : Elements positioned in ascending/descending order of value
    • Unsorted lists : No necessary relationship between element values and positions
  • Functions: Get Value, Insert / Modify / Delete ,Search
  • AST
template <class Elem> class List {
    
    
public:
// reinitialize the list
virtual void clear() = 0; 
// insert an item into the list before the current item
virtual bool insert(const Elem&) = 0; 
// insert an item into the list at the end of the list
virtual bool append(const Elem&) = 0;
// remove the item at the current
virtual bool remove(Elem&) = 0;
//set current to the beginning
virtual void setStart() = 0;
// set current to the last
virtual void setEnd() = 0;
// set current to the previous item
virtual void prev() = 0;
// set current to the next item
virtual void next() = 0;
// the size of the list before the current
virtual int leftLength() const = 0;
// the size of the list after and including the current
virtual int rightLength() const = 0;
// set current to the position indicated by the argument
virtual bool setPos(int pos) = 0;
// return the value of the current item in the argument
virtual bool getValue(Elem&) const = 0;
// print out the items in the list
virtual void print() const = 0;
};

Array-based List

  • ADT
template <class Elem> // Array-based list
class AList : public List <Elem> {
    
    
private:
int maxSize; // Maximum size of list
int listSize; // Actual elem count
int fence; // Position of fence
Elem* listArray; // Array holding list
public:
AList(int size=DefaultListSize) {
    
    
maxSize = size;
listSize = fence = 0;
listArray = new Elem[maxSize];
}
~AList() {
    
    
delete [] listArray;
}
}
  • Insert Function
// Insert at front of right partition
template <class Elem>
bool AList<Elem>::insert(const Elem& item) {
    
    
if (listSize == maxSize)
return false;
for(int i=listSize; i>fence; i--)
// Shift Elems up to make room
listArray[i] = listArray[i-1]; 
listArray[fence] = item;
listSize++; // Increment list size
return true
  • Set Position Function
template <class Elem>
bool AList<Elem>::setPos(int pos) {
    
    
if ((pos >= 0) && (pos <= listSize))
fence = pos;
return (pos >= 0) && (pos <= listSize);
}
  • Get Value Function
template <class Elem> 
int AList<Elem>::rightLength() const {
    
    
return listSize - fence;
}
template <class Elem>
int AList<Elem>::leftLength() const {
    
    
return fence;
}
template <class Elem>
bool AList<Elem>::getValue(Elem& it) const {
    
    
if (rightLength() == 0) return false;
else {
    
    
it = listArray[fence];
return true;
}
  • Append Function
template <class Elem>
bool AList<Elem>::append(const Elem& item) 
{
    
    
if (listSize == maxSize) return false;
listArray[listSize++] = item;
return true;
}
  • Remove Function
// Remove and return first Elem in right partition
template <class Elem>
bool AList<Elem>::remove(Elem& it) {
    
    
if (rightLength() == 0) return false;
it = listArray[fence]; // Copy Elem
for(int i=fence; i<listSize-1; i++)
listArray[i] = listArray[i+1]; // Shift them down
listSize--; // Decrement size
return true;
}
  • Other Functions
template <class Elem>
void AList<Elem>::setStart() {
    
     fence = 0; }
template <class Elem>
void AList<Elem>:: setEnd() {
    
     fence = listSize; }
template <class Elem>
void AList<Elem>:: prev() {
    
     if (fence != 0) fence--; }
template <class Elem>
void AList<Elem>:: next() 
{
    
     if (fence <= listSize-1) fence++; }
template <class Elem>
void AList<Elem>:: print() const {
    
    
int temp = 0;
cout <<<;
while (temp < fence)
cout << listArray[temp++] << ” ”;
cout <<|;
while (temp < listSize)
cout << listArray[temp++] << ” ”;
cout <<>\n ”;
}

Linked List

  • Node
// Linked list node
template <class Elem> class Link {
    
    
public:
Elem element; // Value for this node
Link *next; // Pointer to next node
Link(const Elem& elemval, Link* nextval=NULL){
    
     
element = elemval; 
next = nextval; 
}
Link(Link* nextval=NULL){
    
     
next = nextval; 
}
};
  • Implementation
// Linked list implementation
template <class Elem> 
class LList : public List<Elem> {
    
    
private:
	Link<Elem>* head; //Point to list header
	Link<Elem>* tail; //Pointer to last Elem
	Link<Elem>* fence; //Last element on left
	int leftcnt; //Size of left
	int rightcnt; //Size of right
	void init() {
    
     //Initialization routine
		fence = tail = head = new Link<Elem>;
		leftcnt = rightcnt = 0;
	}
	void removeall() {
    
    //Remove link nodes to free store
		while(head != NULL) {
    
    
			fence = head;
			head = head->next;
			delete fence;
		}	
	}
}
  • Insert Function
// Insert at front of right partition
template <class Elem>
bool LList<Elem>::insert(const Elem& item) {
    
    
	fence->next = new Link<Elem>(item, fence->next); 
	if (tail == fence)
		tail = fence->next; 
	rightcnt++;
	return true;
}
  • Set Position Function
// Set the size of left partition to pos
template <class Elem>
bool LList<Elem>::setPos(int pos) {
    
    
	if ((pos < 0) || (pos > rightcnt+leftcnt)) 
		return false;
	fence = head;
	for(int i=0; i<pos; i++)
		fence = fence->next;
	rightcnt = rightcnt+leftcnt-pos;
	leftcnt = pos;
	return true;
}
  • Get Value Function
template <class Elem>
int LList<Elem>:: rightLength() const {
    
     return rightcnt; }
template <class Elem>
int LList<Elem>:: leftLength() const {
    
     return leftcnt; }
template <class Elem>
bool LList<Elem>:: getValue(Elem& it) const {
    
    
	if(rightLength() == 0) 
		return false;
	it = fence->next->element;
	return true;
}
  • Append Function
// Append Elem to end of the list
template <class Elem>
bool LList<Elem>::append(const Elem& item) {
    
    
	tail = tail->next = new Link<Elem>(item, NULL);
	rightcnt++;
	return true;
}
  • Remove Function
// Remove and return first Elem in right partition
template <class Elem> 
bool LList<Elem>::remove(Elem& it) {
    
    
	if (fence->next == NULL) return false;
	it = fence->next->element; // Remember val
	Link<Elem>* ltemp = fence->next; // Remember link node
	fence->next = ltemp->next; // Remove
	if (tail == ltemp) // Reset tail
		tail = fence;
	delete ltemp; // Reclaim space
	rightcnt--;
	return true;
}
  • Set Start and Set End Functions
template <class Elem>
void LList<Elem>:: setStart() {
    
     
	fence = head; 
	rightcnt += leftcnt;
	leftcnt = 0;
}
template <class Elem>
void LList<Elem>:: setEnd() {
    
    
	fence = tail; 
	leftcnt += rightcnt ;
	rightcnt = 0;
}
  • Previous Functions
template <class Elem>
void LList<Elem>:: prev() {
    
    
	Link<Elem>* temp = head;
	if (fence == head) return; // No prev Elem
	while (temp->next!=fence)
		temp=temp->next;
	fence = temp;
	leftcnt--;
	rightcnt++;
}
  • Next Functions
template <class Elem>
void LList<Elem>:: next() {
    
    
	if (fence == tail) return; // No next Elem
	fence = fence->next;
	leftcnt++;
	rightcnt--;
}
  • Print Functions
template <class Elem>
void LList<Elem>:: print() const {
    
    
	Link<Elem>* temp = head;
	cout <<<;
	while (temp != fence) {
    
    
		cout << temp->next->element << ” ”;
		temp = temp->next;
	}
	cout <<|;
	while (temp->next != NULL) {
    
    
		cout << temp->next->element << ” ”;
		temp = temp->next;
	}
	cout <<>\n”;
}
  • Examples

Q1: Write a swap function to swap two adjacent elements (fence->next, fence->next->next) of a linked list by adjusting only the pointers

template <class Elem>
bool LList<Elem>:: swap() {
     
     
	if (fence == tail) return false;
	if (fence->next == tail) return false;
	Link<Elem>* temp = fence->next;
	fence->next = temp->next;
	temp->next = fence->next->next;
	fence->next->next = temp;
	if (fence->next == tail)
	tail = tail->next;
} 

注意判断条件

Q2: Write a findNdel function which deletes all the occurrence of a given ITEM in a linked list (Do no use remove() function)

template <class Elem>
bool LList<Elem>:: findNdel(Elem value) {
     
     
	if (head == tail) return false;
	Link<Elem>* temp;
	Link<Elem>* ptr = head;
	bool beforeFence = true;
	while (ptr <> tail) {
     
          // check if the ptr passes by fence
		if (ptr == fence->next) beforeFence = false;
		if (ptr->next->element == value) {
     
      // check the list
			if (fence == ptr->next) fence = ptr;
			if (tail == ptr->next) tail = ptr;
			temp = ptr->next;
			ptr->next = ptr->next->next;
			delete temp;
			if (beforeFence) leftcnt--;
			else rightcnt--;
	}
	else
		ptr = ptr->next;
}
	return true;
}
  • Freelists

    • Concept of Freelists
    1. Put the deleted nodes in the freelist
    2. When a new node is needed, get it from the
      freelist
    3. When a node is deleted, it is placed at the head of the freelist
    4. When a new node is to be added, the freelist is checked to see if a freelist is empty. If so, the standard new operator will be called. If not, a node is taken from the freelist.
    • Template
    // Singly-linked list node with freelist
    template <class Elem> class Link {
          
          
    private:
       static Link<Elem>* freelist; // Head
    public:
       Elem element; // Value for this node
       Link* next; // Point to next node
       Link(const Elem& elemval, Link* nextval =NULL)
       		{
          
           element = elemval; next = nextval; }
       Link(Link* nextval =NULL) 
       		{
          
           next=nextval; }
       void* operator new(size_t); // Overload new operator
       void operator delete(void*); // Overload delete operator
    };
    
    • Overload delete
    template <class Elem> // Overload delete
    void Link<Elem>::operator delete(void* ptr) {
          
          
       ((Link<Elem>*)ptr)->next = freelist;
       freelist = (Link<Elem>*)ptr;
    }
    
    • Overload new
    template <class Elem> // Overload new
    void* Link<Elem>::operator new(size_t) {
          
          
    	if (freelist == NULL) return ::new Link;
    	Link<Elem>* temp = freelist; // Reuse
    	freelist = freelist->next;
    	return temp; // Return the link
    }
    

Comparison

  • Array Lists
    • Insertion and deletion are Θ ( n ) Θ(n) Θ(n)
    • Prev and direct access are Θ ( 1 ) Θ(1) Θ(1)
    • Array must be allocated in advance
    • No overhead if all array positions are full
  • Linked Lists
    • Insertion and deletion are Θ ( 1 ) Θ(1) Θ(1)
    • Prev and direct access are Θ ( n ) Θ(n) Θ(n)
    • Space grows with number of elements
    • Every element requires overhead
  • Memory Space
    • Array-Based Lists D E DE DE
    • Linked Lists : n ( E + P ) n(E + P) n(E+P)
      E: Space for data value
      P: Space for pointer
      D: Number of elements in array
      n: Number of current elements

Doubly Linked List

  • Templete
// Doubly-linked list link node
template <class Elem> class Link {
    
    
public:
	Elem element; // Value for this node
	Link *next; // Pointer to next node 
	Link *prev; // Pointer to previous node
	Link(const Elem& e, Link* prevp=NULL, Link* nextp=NULL) 
		{
    
     element=e; prev=prevp; next=nextp; }
	Link(Link* prevp=NULL, Link* nextp=NULL)
		{
    
     prev=prevp; next=nextp; }
};
  • Insert Function
// Insert at front of right partition
template <class Elem>
bool LList<Elem>::insert(const Elem& item) {
    
    
	fence->next = new Link<Elem>(item, fence, fence->next); 
	if (fence->next->next != NULL)
		fence->next->next->prev = fence->next;
	if (tail == fence) // Appending new Elem
		tail = fence->next; // Set tail
	rightcnt++; // Added to right
	return true;
}
  • Remove Function
// Remove, return first Elem in right part
template <class Elem>
bool LList<Elem>::remove(Elem& it) {
    
    
	if (fence->next == NULL) 
		return false;
	it = fence->next->element;
	Link<Elem>* ltemp = fence->next;
	if (ltemp->next != NULL)
		ltemp->next->prev = fence;
	else tail = fence; // Reset tail
	fence->next = ltemp->next; // Remove
	delete ltemp; // Reclaim space
	rightcnt--; // Removed from right
	return true;
}
  • Previous Function
template <class Elem>
void LList<Elem>::prev() {
    
    
	// no prev Elem
	if (fence != head) {
    
     
		fence = fence->prev;
		leftcnt--;
		rightcnt++;
	}
}

Stacks

  • Restricted form of a List
    1. Insert only at the front
    2. Remove from the front
  • First-In-Last-Out (FILO)
  • Notation
    1. Insert: PUSH
    2. Remove: POP
    3. The accessible element is called TOP

Array-based Stack

  • Templete
    	template <class Elem> class AStack: public Stack<Elem> {
          
          
    	private:
    		int maxSize; // Maximum size of stack
    		int top; // Index for top element
    		Elem *listArray; // Array holding stack elements
    	public:
    		AStack(int size =DefaultListSize) // Constructor
    			{
          
           maxSize = size; top = 0; listArray = new Elem[size]; }
    		~AStack() {
          
           delete [] listArray; } // Destructor
    		
    
  • Push Function
    template <class Elem> class AStack: public Stack<Elem> {
          
          
    private:
    	int maxSize; // Maximum size of stack
    	int top; // Index for top element
    	Elem *listArray; // Array holding stack elements
    public:
    	AStack(int size =DefaultListSize) // Constructor
    		{
          
           maxSize = size; top = 0; listArray = new Elem[size]; }
    	~AStack() {
          
           delete [] listArray; } // Destructor
    	};	
    
  • Pop Function
    template <class Elem> 
    bool AStack<Elem>:: bool pop(Elem& it) {
          
          
    // Pop top 	element
    if (top == 0) return false;
    else {
          
           
    	it = listArray[--top]; 
    	return true; 
    	}
    }
    

Linked Stack

  • Template
    template <class Elem> class LStack: public Stack<Elem> {
          
          
    private:
    	Link<Elem>* top; // Pointer to first element
    	int size; // Number of elements
    public:
    	LStack(int sz =DefaultListSize) {
          
           top = NULL; size = 0; }
    	~LStack() {
          
           clear(); } // Destructor
    }
    
  • Push Function
    template <class Elem> 
    bool LStack<Elem>:: push(const Elem& it) {
          
           // Put it on stack
    	top = new Link<Elem>(it, top);
    	size++;
    	return true;
    }
    
  • Pop Function
    template <class Elem> 
    bool LStack<Elem>:: bool pop(Elem& it) {
          
           // Remove it from stack
    	if (size == 0) return false;
    	it = top->element;
    	Link<Elem>* ltemp = top->next;
    	delete top;
    	top = ltemp;
    	size--;
    	return true;
    }
    

Queues

  • Restricted form of a list
  1. Insert at one end
  2. Remove from the other end
  • First-In-First-Out (FIFO)
  • Notation
  1. Insert: Enqueue
  2. Delete: Dequeue
  3. First Element: FRONT
  4. Last Element: REAR

Array-based Queue

  • Template
template <class Elem> class AQueue: public Queue<Elem> {
    
    
	private:
		int size; // Maximum size of queue
		int front; // Index of front element
		int rear; // Index of rear element
		Elem *listArray; // Array holding queue elements
	public:
		AQueue(int sz =DefaultListSize) {
    
     // Constructor
		// Make list array one position larger for empty slot
		size = sz+1;
		rear = 0; front = 1;
		listArray = new Elem[size];
}
	~AQueue() {
    
     delete [] listArray; } // Destructor
}
  • Enqueue Function
template <class Elem> 
bool AQueue <Elem>::enqueue(const Elem& it) {
    
     // Put element on rear
		if (rear == size) return false; // Full
		rear = rear+1; // increment
		listArray[rear] = it;
		return true;
}
  • Dequeue Function
template <class Elem> 
bool AQueue <Elem>::dequeue(Elem& it) {
    
     // Take element out
	if (length() == 0) return false; // Empty
	it = listArray[front];
	front = front+1; // Circular increment
	return true;
}
  • Circular Queue
template <class Elem> 
bool LQueue <Elem>:: enqueue(const Elem& it){
    
    
	if (((rear+2) % size) == front) return false; // Full
	rear = (rear+1) % size; // Circular increment
	listArray[rear] = it;
	return true;
}

template <class Elem> 
bool LQueue <Elem>:: dequeue(Elem& it) {
    
     
	if (length() == 0) return false; // Empty
	it = listArray[front];
	front = (front+1) % size; // Circular increment
	return true;
}

Linked Queue

  • Template
template <class Elem> class LQueue: public Queue<Elem> {
    
    
	private:
		Link<Elem>* front; // Pointer to front queue node
		Link<Elem>* rear; // Pointer to rear queue node
		int size; // Number of elements in queue
	public:
		LQueue(int sz =DefaultListSize) // Constructor
			{
    
     front = NULL; rear = NULL; size = 0; }
		~LQueue() {
    
     clear(); } // Destructor
}
  • Enqueue Function
template <class Elem> 
bool LQueue <Elem>::enqueue(const Elem& it) {
    
     // Put element on rear
	if (rear == NULL) // Empty queue
		front = rear = new Link<Elem>(it, NULL);
	else {
    
     // Append new node
		rear->next = new Link<Elem>(it, NULL);
		rear = rear->next;
	}
	size++;
	return true;
}
  • Dequeue Function
template <class Elem> 
bool LQueue <Elem>::dequeue(Elem& it) {
    
     // Remove element from front
	if (size == 0) return false; // Empty
	it = front->element; // Store dequeued value
	Link<Elem>* ltemp = front; // Hold dequeued 	link
	front = front->next; // Advance front
	delete ltemp; // Delete link
	if (front == NULL) rear = NULL; // Dequeued last element
	size --;
	return true; // Return element value
}

Dictionary Example

猜你喜欢

转载自blog.csdn.net/yxyxxxyyyy/article/details/119212818