数据结构C++语言描述专题系列 (四) 链式栈和队列

1、指针与链表

一、指针

指针是一种数据类型,具有指针类型的变量称为指针变量。但事实上,可以将指针直接看成一种特殊的变量。首先,它与一般变量一样具有变量的三个基本要素:名字、类型和值,不同点主要在于类型和值上,指针命名与一般变量命名一样,都用标识符。

指针所存放的是某个变量的地址值,或者说它所表示的数据值是某个变量在内存中的地址值。通常所说的指针存放哪个变量的地址值,它就指向那个变量。

指针的类型是它所指向变量的类型,而不是指针本身数据值的类型,因为任何指针它本身数据值的类型都是unsigned long int型。

空指针 NULL
当前不指向具体的对象,不同的系统会使编译取不同的NULL值。在PC中的BC或VC,都取值0。如果考虑到移植,不要养成把NULL当成为0的习惯。

二、链式结构

这里写图片描述

每一个结点的地址存放在它前面的结点的指针域中。

结点的定义
struct Node {
//  data members
   Node_entry entry;
   Node *next;
//  constructors
   Node( );
   Node(Node_entry item, Node *add_on = NULL);
};
结点的构造函数(Constructors)
Node ∷Node( )
{
   next = NULL;
}
Node ∷Node( Node_entry item, Node *add_on)
{
   entry = item;
   next = add_on;
}

在使用中,第二个构造函数的第二个参数可以按缺省处理,即可作为NULL。也就是说第二个构造函数有2种方法引用,2个参数或1个参数。第二种情况下,第二个参数取缺省值NULL。

例
Node first_node(‘a’);
Node *p0 = &first_node;
Node *p1 = new Node(‘b’);
p0->next = p1;
Node *p2 = new Node(‘c’, p0);
p1->next = p2;

这里写图片描述

2、链式栈

如何实现链式栈
链式栈的组织形式

这里写图片描述

与顺序存储的栈区别

这里写图片描述

链式栈类说明

class Stack{
public:
    Stack( );
    bool empty( ) const;
    Error_code push(const Stack_entry &item);
    Error_code pop( );
    Error_code top(Stack_entry &item) const;
protected:
    Node *top_node;
};

链式栈的图示

这里写图片描述

链式栈的入栈运算

Error_code Stack ∷push(const Stack_entry &item)
/* Post: Stack_entry item is added to the top of the Stack; returns success or returns a code of overflow if dynamic menory is exhausted */
{
   Node *new_top = new Node(item, top_node);
   if(new_top = = NULL) return overflow;
   top_node = new_top;
   return success;
}

链式栈的出栈运算

Error_code Stack ∷pop( )
/* Post: The top of the Stack is removed. If the Stack is empty the method returns underflow; otherwise it returns success */
{
   Node *old_top = top_node;
   if(top_node = = NULL) return underflow;
   top_node = old_top - >next;
   delete old_top;
   return success;
}

这里写图片描述

关于链式栈运算的副作用问题

例 一、 for(int i= 1; i<1000000; i + +)
               {
                   Stack small;     
                   small.push(some.data); 
               }

每次迭代产生一个stack对象,数据加入到相应的存储空间。因为动态生成,前次存储的数据会成为碎片,积累到一定程度引起系统崩溃。引入析构函数(destructor)。

Stack ∷~Stack( )
/* Post: The Stack is cleared. */
{
    while (!empty( ))  pop( );
}

产生垃圾(garbage)

例二、Stack outer_stack;
             for (int i = 0; i<1000000; i + +) {
                 Stack inner_stack;
                 inner_stack.push(some_data);
                 inner_stack = outer_stack;
              }
例三、
void destroy_the_stack (Stack copy)
{
}
int main( )
{
     Stack vital_data;
     destroy_the_stack(vital_data);
}

链式栈改进方法
赋值重载

void Stack:: operator = (const Stack &original) // Overload assignment
/* Post: The Stack is reset as a copy of Stack original. */
{
   Node *new_top, *new_copy, *original_node = original.top_node;
   if (original_node = = NULL) new_top = NULL;
     else {                   // Duplicate the linked nodes
       new_copy = new_top = new Node(original_node − >entry);
       while (original_node −>next != NULL) {
           original_node = originaLnode − >next;
           new_copy − >next = new Node(original_node − >entry);
           new_copy = new_copy − >next;
        }
   }
   while (! empty( ))         // Clean out old Stack entries
       pop( );
   top_node = new_top;     // and replace them with new entries.
}

拷贝方法的改进

Stack:: Stack(const Stack &original)      // copy constructor
/* Post: The Stack is initialized as a copy of Stack original. */
{
    Node *new_copy, *original_node = original.top_node;
    if (original_node = = NULL)  top_node = NULL;
    else {                   // 复制链式栈的结点
       top_node = new_copy = new Node(original_node − >entry);
       while (original_node − >next ! = NULL) {
            original_node = original_node − >next;
            new_copy − >next = new Node(original_node − >entry);
            new_copy = new_copy − >next;
       }
     }
}

修改后的链式栈说明

class Stack {
public:
//   标准的栈方法
   Stack( );
   bool empty( ) const;
   Error_code push(const Stack_entry &item);
   Error_code pop( );
   Error_code top(Stack_entry &item) const;
//  关于链式栈的安全的特殊方法
   ~ Stack( );
   Stack(const Stack &original);
   void operator = (const Stack &original);
protected:
    Node *top_node;
};

3、链式队列

链式队列的操作示意

这里写图片描述

链式队列的说明

class Queue {
public:
// standard Queue methods
  Queue( );
  bool empty( ) const:
  Error_code append (const Queue_entry &item);
  Error_code serve( );
  Error_code retrieve (Queue_entry &item) const;
// safety features for linked structures
  ~ Queue( ):
  Queue (const Queue &original);
  void operator = (const Queue &Original);
  protected:
    Node *front, *rear;
 }:

链式队列的构造函数与入队列操作

构造函数

Queue:: Queue( )
/* Post: The Queue is initialized to be empty */
{
    front = rear = NULL;
}

入队列操作

Error_code Queue:: append (const Queue_entry &item)
/* Post: Add item to the rear of the Queue and return a code of success or return a code of overflow if dynamic memory is exhausted. */
{
    Node *new_rear = new Node(item);
    if (new_rear = = NULL) return overflow;
    if (rear = = NULL) front = rear = new_rear;
      else {.
          rear - >next = new_rear;
          rear = new_rear;
       }
     return success;
}

链式队列的出队列操作

Error_code Queue:: serve( )
/* Post: The front of the Queue is removed. If the Queue is empty return an Error_code overflow. */
{
    if (front = = NULL) return underflow;
    Node *old_front = front;
    front = old_front - >next;
    if (front = = NULL) rear = NULL;
    delete old_front;
     return success:
}

派生链式队列与其长度函数

class Extended_queue: public Queue {
public:
   bool full( ) const;
   int size( ) const;
   void clear( );
   Error_code serve_and_retrieve(Queue_entry &item);
};
int Extended_queue:: size( ) const
/* post: return the number of entries in the Extended_queue. */
{
    Node *window = front;
    int count = 0;
    while(window ! = NULL) {
        window = window - >next;
        count + +;
    }
    return count;
}

4、多项式及其计算

需要解决的问题:多项式的表示及计算算法。

struct Term {
    int degree;
    double coefficient;
    Term (int exponent = 0, double scalar = 0):
};

Term:: Term(int exponent, double scalar)
/* Post: The Term is initialized with the given coefficient and exponent, or with default parameter values of 0. */
{
    degree = exponent;
    coefficient = scalar;
}

链表的应用

  1. 多项式

这里写图片描述

多项式相加

这里写图片描述

相加算法思想

这里写图片描述

多项式存储结构
链式栈、队列、通常的单链表,也可以是连续存储结构。视具体应用需要而定。

多项式的运算
基本程序

int mainO
/* Post: The program has executed simple polynomialarithmetic comi
tered by the user.
Uses: The classes Stack and Polynomial and the functions introductio
tions, do_command, and get_command. */
{
Stack stored_polynomials;
introductionO;
instructionsO;
while (do_command(get_command(), stored_polynomials));
}

多项式运算(do command命令)

bool do_command(char command. Stack &stored_polynomials)
/* Pre: The first parameter specifies a valid calculator command.
Post: The command specified by the first parameter has been applie
Stack of Polynomial objects given by the second parameter. A
true is returned unless command == 'q'.   A"^-" ' S-y*
Uses: The c/asses Stack and Polynomial. */           D     '‘
{
Polynomial p, q, r;
switch (command) {
case '?':
p.readO;
if (stored_polynomials.,push(p) == overflow)
cout « "Warning: Stack full, lost polynomial" « endl;
break;            
case '=':
if (stored_polynomials.empty())
cout « "Stack empty" « endl;
else {
stored_polynomials.top(p);
p.printO;
}
break;
case'+':
if (storecLpolynomials.emptyO)
cout« "Stack empty" « endl;
else{
stored_polynomials.top(p); (?y{i-^a ^<%»/ |,
storecLpolynomials.popO;     3; ^'
if(stored_polynomials.empty()) {
cout « "Stack has just one polynomial" « endl;
stored_polynomials.push(p);
}
else{
»   stored_polynomials.top(q);
stored_polynomials.pop();
r.equals_sum(q, p);     f '^- ^+ P
if (stored_polynomials.push(r) == overflow)
cout « "Warning: Stack full, lost polynomial" « endl;
}
break;
// Add options for further user commands.
case 'q':                 ~^^-
cout « "Calculation finished." « endl;
return false;
}
return true;
}

多项式类的说明

class Polynomial {
public:
void read();
void printO;
void equals_sum(Polynomial p. Polynomial q);
void equals_difference(Polynomial p. Polynomial q);
void equals_product(Polynomial p. Polynomial q);
Error_code equals_quotient(Polynomial p. Polynomial q);
private:
double value;
};
class Polynomial: private Extended_queue { //  Use private inheritance.
public:                                                            .
   void read( );              
   void print( ) const;
   equals_sum(Polyoornial p. Polynomial q);
   void equals_difference(Polynomial p. Polynomial q);           
   void equals_product(Polynomial p. Polynomial q);            
   Error_code equals_quotient(Polynom»al p. Polynomial q);
   int degree() const;    
private:              
   void mult_term(Polynomial p. Term t); 
} 

多项式的打印

void Polynomial:: print( ) const
/* Post: The Polynomial /s printed to cout */
   Node *print_node = front;      
   bool first_term= true;
   while (print.node != NULL) {  
       Term &print_term = print_node->entry;
       if (first_term) {          //  In this case, suppress printing an initial'+'
first_term = false;
        if (print_term.coefficient < 0) cout « " - ";   
}
else if (print_term.coefficient < 0) cout « " - ";
else cout « " + ";
double r = (print_term.coefficient >= 0)   
                   ? print_term.coefficient: -(print_term.coefficient);
if(r != 1) cout « r;
if (print.term.degree > 1) cout « " X"" « print_term.degree;
if (print_term. degree == 1) cout « " X";
if (r == 1 && print_term.degree == 0) cout « " 1";
        print.node = print_node->next;    
        }
       if (first.term)
           cout « “0";           // Print 0 for an empty Polynomial.
       cout« end l;

多项式的读取

void Polynomial:: read( ) 
/* Post: The Polynomial /s read from cin. */ 
{
   clear( );
   double coefficient;     
   int last_exponent, exponent; 
   bool first_term = true;
   cout « "Enter the coefficients and exponents for the polynomial, "
  « "one pair per line. Exponents must be in descending order." « endl
  « "Enter a coefficient of 0 or an exponent of 0 to terminate." «endl;

多项式的读取

do {
       cout « "coefficient? " « flush; 
       cin  »coefficient;              
       if (coefficient != 0.0) {           
          cout « "exponent? " « flush;                    
          cin  » exponent;        
          if ((! first_term && exponent >= last_exponent) || exponent < 0) {
             exponent =0;      
             cout « "Bad exponent: Polynomial terminates without its last term « endl;
           }
         else {
            Term new_term(exponent, coefficient);
            append(new_term);
            first_term = false;
           }
           last_exponent = exponent; 
          }
       } while (coefficient != 0.0 && exponent !=0);
}

多项式加法

void Polynomial ::equals_sum(Polynomial p, Polynomial q)
/* Post: The Polynomial object is reset as the sum of the two parameters. */
{
    dear( );
    while (!p.empty( ) || !q.empty( )){
        Term p_term, q_term;
        if (p.degree( ) > q.degree( )) {
            p.serve_and_retrieve(p_term);
            append(p_term);
        }
        else if (q.degree( ) > p.degre( )) {
            q.serve_and_retrieve(q_term);
            append(q_term);
         }
        else{
           p.serve_and_retrieve<p_term);
           q.serve_and_retrieve(q_term);
           if (p_term.coefficient + q_term.coefficient ! = 0) {
                Term answer_term(p_term.degree, p_term.coefficient + q_term.coefficient);
                append(answer_term);
            }
        }
    }
}

持续更新中。。。

数据结构C++语言描述专题系列 (一) 绪论
数据结构C++语言描述专题系列 (二) 栈
数据结构C++语言描述专题系列 (三) 队列
数据结构C++语言描述专题系列 (四) 链式栈和队列
数据结构C++语言描述专题系列 (五) 递归
数据结构C++语言描述专题系列 (六) 表与串
数据结构C++语言描述专题系列 (七) 查找
数据结构C++语言描述专题系列 (八) 排序
数据结构C++语言描述专题系列 (九) 表与信息检索
数据结构C++语言描述专题系列 (十) 二叉树
数据结构C++语言描述专题系列 (十一) 多路数
数据结构C++语言描述专题系列 (十二) 集合及其表示
数据结构C++语言描述专题系列 (十三) 图
数据结构C++语言描述专题系列 (十四) 波兰表达式

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值