程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++若何完成狹義表詳解

C++若何完成狹義表詳解

編輯:關於C++

C++若何完成狹義表詳解。本站提示廣大學習愛好者:(C++若何完成狹義表詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是C++若何完成狹義表詳解正文


以下給出幾種簡略的狹義表模子:

 

由上圖我們可以看到,狹義表的節點類型不過headvaluesub三種,這裡設置列舉類型,應用列舉變量來記載每一個節點的類型:

enum Type
{
  HEAD,  //頭節點
  VALUE, //值節點
  SUB,  //子表節點
};

每一個節點都有本身的類型和next指針,除此以外,假如該節點是VALUE類型還要分派空間存儲該節點的有用值;然則若該節點是SUB類型,就需界說一個指針指向子表的頭。

這裡我們可以用結合來處理這個成績。

(結合(或配合體)是一種分歧數據類型成員之間同享存儲空間的辦法,而且結合體對象在統一時光只能存儲一個成員值)

結構節點:

struct GeneralizedNode
{
  Type _type;    // 1.類型
  GeneralizedNode* _next; //2.指向同層的下一個節點
  union
  {
    char _value;  // 3.有用值
    GeneralizedNode* _subLink;   // 3.指向子表的指針
  };
   
  GeneralizedNode(Type type = HEAD, char value = '0')
  :_value(value)
  ,_type(type)
  , _next(NULL)
  {
    if (_type == SUB)
    {
      _subLink = NULL;
    }
  }
};

狹義表的界說及根本操作: 

class Generalized
{
public:
  //無參的結構函數,樹立空的狹義表
  Generalized();
  //建造狹義表,有參數的結構函數
  Generalized(const char* str);
  //打印狹義表
  void Print();
  //獲得值節點的個數
  size_t Amount();
  //獲得狹義表的深度
  size_t Depth();
  //拷貝結構
  Generalized(const Generalized& g);
  ////賦值運算符的重載
  Generalized& operator=(const Generalized& g);
  ////析構函數
  ~Generalized();
 
protected:
  void _Print(GeneralizedNode* head);
  GeneralizedNode* _CreatList(const char*& str);
  size_t _Amount(GeneralizedNode* head);
  GeneralizedNode* _Copy(GeneralizedNode* head);
  void _Destory(GeneralizedNode* head);
protected:
  GeneralizedNode* _head;  //記載狹義表頭指針
};

初始化樹立狹義表停止輪回遞歸。遍歷字符串時碰到字符就樹立值節點,碰到'('就停止遞合並樹立子表;碰到')'就停止以後子表的樹立,並前往以後子表的頭指針。 

GeneralizedNode* _CreatList(const char*& str)
{
  assert(*str == '(');
  GeneralizedNode* head = new GeneralizedNode(HEAD,'0');
  GeneralizedNode* cur = head;
  str++;
  while (str != '\0')
  {
    if ((*str >= '0'&&*str <= '9') || (*str >= 'a'&&*str <= 'z') || (*str >= 'A'&&*str <= 'Z'))
    {
      cur->_next = new GeneralizedNode(VALUE, *str);
      cur = cur->_next;
    }
    else if (*str == '(')
    {
      cur->_next = new GeneralizedNode(SUB);
      cur = cur->_next;
      cur->_subLink = _CreatList(str);
    }
    else if (*str == ')')
    {
      return head;
    }
    str++;
  }
  return head;
}

打印狹義表:當節點的類型為SUB時停止遞歸,最初不要忘了每打印完一層要打印一個後括號。

void _Print(GeneralizedNode* head)
{
  if (head == NULL)
  {
    cout << "Generalized table is NULL" << endl;
    return;
  }
  GeneralizedNode* cur = head;
  while (cur)
  {
    if (cur->_type == HEAD)
    {
      cout << '(';
    }
    else if (cur->_type == VALUE)
    {
      cout << cur->_value;
      if (cur->_next)
      {
        cout << ',';
      }
    }
    else if (cur->_type == SUB)
    {
      _Print(cur->_subLink);
      if (cur->_next)
      {
        cout << ',';
      }       
    }
    cur = cur->_next;
  }
  cout << ')';
}

獲得值節點的個數:設置count變量,碰到值節點就加1,碰到SUB節點停止遞合並將前往值加給count

size_t _Amount(GeneralizedNode* head)
{
  GeneralizedNode* begin = head;
  size_t count = 0;
  while (begin)
  {
    if (begin->_type == VALUE)
    {
      count++;
    }
    if (begin->_type == SUB)
    {
      count += _Amount(begin->_subLink);
    }
    begin = begin->_next;
  }
  return count;
}

狹義表的深度:設置變量dp和max分離用來記載以後子表即以後SUB節點指向的子表深度,和本層一切的SUB節點中深度最年夜的子表的深度。

size_t _Depth(GeneralizedNode* head)
{
  if (_head == NULL)
  {
    return 0;
  }
  size_t dp=0;
  GeneralizedNode* cur = head;
  size_t max = 0;
  while (cur)
  {
    if (cur->_type == SUB)
    {
      dp=_Depth(cur->_subLink);
      if (max < dp)
      {
        max = dp;
      }
    }
    cur = cur->_next;
  }
  return max+1;
}

燒毀狹義表:順次遍歷節點,碰到子表遞歸,將子表的節點delete完成後,再回到以後層持續遍歷。

void _Destory(GeneralizedNode* head)
{
  if (head == NULL)
  {
    return;
  }
  while (head)
  {
    GeneralizedNode* begin = head->_next;
    if (head->_type == SUB)
    {
      _Destory(head->_subLink);
    }
    delete head;
    head = begin;
  }
}

實例演示

界說:

狹義表是n(n≥0)個元素a1,a2,…,ai,…,an的無限序列。

  個中:

  ①ai--或許是原子或許是一個狹義表。

  ②狹義表平日記作:

  Ls=( a1,a2,…,ai,…,an)。

  ③Ls是狹義表的名字,n為它的長度。

  ④若ai是狹義表,則稱它為Ls的子表。

  留意:

  ①狹義表平日用圓括號括起來,用逗號分隔個中的元素。

  ②為了辨別原子和狹義表,書寫時用年夜寫字母表現狹義表,用小寫字母表現原子。

  ③若狹義表Ls非空(n≥1),則al是LS的表頭,其他元素構成的表(a1,a2,…,an)稱為Ls的表尾。

  ④狹義表是遞歸界說的

繪圖舉例:

代碼完成:

[cpp] view plain copy
#include <iostream> 
 
using namespace std; 
 
//表現狹義表的結點類型 
enum NodeType 
{ 
  HEAD_TYPE,//頭結點類型 
  VALUE_TYPE,//值結點類型 
  SUB_TYPE//子表類型 
}; 
 
//表現狹義表結點的構造體 
struct GeneraListNode 
{ 
  NodeType _type;//結點類型 
  GeneraListNode *_next;//寄存結點的下一個元素的地址 
 
  //一個結點要末是值結點要末是子表,故用結合體來寄存節儉必定的空間 
  //若是值結點則寄存的是值,是子表結點的話寄存的是子表結颔首結點的地址 
  union{ 
    char _value; 
    GeneraListNode *_subLink; 
  }; 
 
  GeneraListNode(NodeType type = HEAD_TYPE, char value = '\0') 
    :_type(type) 
    ,_next(NULL) 
  { 
    if (type == VALUE_TYPE) 
    { 
      _value = value; 
    }else if(type == SUB_TYPE) 
    { 
      _subLink = NULL; 
    } 
 
  } 
 
}; 
 
class GeneraList 
{ 
private: 
  GeneraListNode *_link;//用來寄存狹義表頭結點地址 
public: 
  GeneraList(const char *str) 
    :_link(NULL) 
  { 
    _CreateGeneraList(_link, str);//依據指定序列創立狹義表 
  } 
 
  ~GeneraList() 
  {} 
public: 
  void Print();//對外供給的打印狹義表的接口 
  int Size();//狹義表中值結點的數量的對外獲得接口 
  int Depth();//狹義表的最深條理的對外獲得接口 
private: 
  void _CreateGeneraList(GeneraListNode *& link, const char *& str); 
  bool _IsValue(const char ch);//斷定指定字符能否為值結點所許可的類型 
  int _Size(GeneraListNode *head);//盤算狹義表中值結點的數量的完成 
  int _Depth(GeneraListNode *head);//盤算狹義表的最深條理的完成 
  void _Print(GeneraListNode *link);//打印狹義表的接口的底層完成 
}; 
 
//創立狹義表 
void GeneraList::_CreateGeneraList(GeneraListNode *& link, const char *& str) 
{ 
  //狹義表最前端有一個頭結點,用來記載完成狹義表鏈表的首地址 
  //故每次挪用該創立狹義表的函數起首創立一個頭結點 
  GeneraListNode* head = new GeneraListNode(HEAD_TYPE, NULL); 
  head->_next = NULL; 
  link = head; 
  GeneraListNode* cur = link;//用來記載創立狹義表鏈表時以後創立出的結點地位游標指針 
  str++;//將狹義表序列後移,相當於跳過了'(' 
   
  while(*str != '\0') 
  { 
    if(_IsValue(*str)){//假如以後掃描到的字符是值 
      //創立一個值結點 
      GeneraListNode* newNode = new GeneraListNode(VALUE_TYPE, *str); 
      newNode->_next = NULL; 
      cur->_next = newNode;//將該值結點參加到鏈表中 
      cur = cur->_next;//游標後移 
      str++;//將狹義表序列後移 
    }else if(*str == '('){//假如掃描到'('創立子表結點 
      GeneraListNode* subLink = new GeneraListNode(SUB_TYPE, NULL); 
      subLink->_next = NULL; 
      cur->_next = subLink;//將子表結點參加到鏈表中 
      cur = cur->_next; 
      _CreateGeneraList(cur->_subLink, str);//遞歸創立子表 
    }else if(*str == ')'){ 
      str++; 
      return;//若掃描到')'表現狹義表創立停止 
    }else{ 
      str++;//空格等其他有效字符跳過 
    } 
  } 
} 
 
int GeneraList::Size() 
{ 
  return _Size(_link); 
} 
 
//盤算狹義表值結點的個數 
int GeneraList::_Size(GeneraListNode *head) 
{ 
  int size = 0; 
  GeneraListNode *cur = head; 
  while(cur != NULL){ 
    if(cur->_type == VALUE_TYPE){ 
      ++size;//碰到值結點則將size加一 
    }else if(cur->_type == SUB_TYPE){ 
      size += _Size(cur->_subLink);//碰到子表停止遞歸 
    } 
    cur = cur->_next; 
  } 
  return size; 
} 
 
int GeneraList::Depth() 
{ 
  return _Depth(_link); 
} 
int GeneraList::_Depth(GeneraListNode *head) 
{ 
  int depth = 1,maxDepth = 1;//depth表現以後表的深度,maxDepth表現今朝最年夜的深度 
  GeneraListNode *cur = head; 
  while(cur != NULL){ 
    if(cur->_type == SUB_TYPE){ 
      depth += _Depth(cur->_subLink); 
    } 
    if(depth > maxDepth){//更新最年夜深度 
      maxDepth = depth; 
      depth = 1;//將以後深度復位 
    } 
    cur = cur->_next; 
  } 
  return maxDepth; 
} 
 
void GeneraList::Print() 
{ 
  _Print(_link); 
  cout<<endl; 
} 
 
//打印狹義表 
void GeneraList::_Print(GeneraListNode *link) 
{ 
  GeneraListNode *cur = link;//遍歷狹義表的游標 
  while(cur != NULL){ 
    if(cur->_type == VALUE_TYPE){ 
      cout<<cur->_value; 
      if(cur->_next != NULL) 
      { 
        cout<<','; 
      } 
    }else if(cur->_type == HEAD_TYPE){ 
      cout<<"("; 
    }else if(cur->_type == SUB_TYPE){ 
      _Print(cur->_subLink);//碰到子表遞歸打印 
      if(cur->_next != NULL)//假如打印完子表後狹義表未停止則打印',' 
      { 
        cout<<","; 
      } 
    } 
    cur = cur->_next; 
  } 
  cout<<")"; 
} 
 
bool GeneraList::_IsValue(const char ch) 
{ 
  if(ch >= 'a' && ch <= 'z' || 
    ch >= 'A' && ch <= 'Z' || 
    ch >= '0' && ch <= '(') 
  { 
    return true; 
  } 
  return false; 
} 

測試代碼

[cpp] view plain copy
#include"GeneraList.hpp" 
 
//測試空表 
void Test1() 
{ 
  GeneraList genList("()"); 
  genList.Print(); 
  cout<<"Size is :"<<genList.Size()<<endl; 
  cout<<"Depth is :"<<genList.Depth()<<endl<<endl; 
} 
//測試單層表 
void Test2() 
{ 
  GeneraList genList("(a,b)"); 
  genList.Print(); 
  cout<<"Size is :"<<genList.Size()<<endl; 
  cout<<"Depth is :"<<genList.Depth()<<endl<<endl; 
} 
//測試雙層表 
void Test3() 
{ 
  GeneraList genList("(a,b,(c,d))"); 
  genList.Print(); 
  cout<<"Size is :"<<genList.Size()<<endl; 
  cout<<"Depth is :"<<genList.Depth()<<endl<<endl; 
} 
//測試多層表 
void Test4() 
{ 
  GeneraList genList("(a,b,(c,d),(e,(f),h))"); 
  genList.Print(); 
  cout<<"Size is :"<<genList.Size()<<endl; 
  cout<<"Depth is :"<<genList.Depth()<<endl<<endl; 
} 
//測試多層空表 
void Test5() 
{ 
  GeneraList genList("(((),()),())"); 
  genList.Print(); 
  cout<<"Size is :"<<genList.Size()<<endl; 
  cout<<"Depth is :"<<genList.Depth()<<endl<<endl; 
} 
 
int main() 
{ 
  Test1(); 
  Test2(); 
  Test3(); 
  Test4(); 
  Test5(); 
  return 0; 
} 

運轉成果

總結

以上就是關於C++若何完成狹義表詳解的全體內容,願望對有須要的人能有所贊助,假如有疑問迎接年夜家留言評論辯論。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved