編程題——21~30

二11、包含min函數的棧

     定義棧的數據結構,請在該類型中實現一個可以獲得棧的最小元素的min函數。在該棧中,調node

用min、push及pop的時間複雜度都是O(1)。ios

/*
  定義棧的數據結構,請在該類型中實現一個可以獲得棧的最小元素的min函數。在該棧中,
  調用min、push及pop的時間複雜度都是O(1)。
*/

#include <iostream>
#include <stack>
#include <assert.h>
#include <stdio.h>

template <typename T> class StackWithMin
{
  public:
    StackWithMin( void ) { }
    virtual ~StackWithMin( void ) { }
    
    T& top( void );
    const T& top( void ) const;
    
    void push( const T& value );
    void pop( void );
   
    const T& min( void ) const;
    
    bool empty() const;
    size_t size() const;
 
  private:
    std::stack<T> m_data;
    std::stack<T> m_min;
};

template<typename T> void StackWithMin<T>::push( const T& value )
{
  m_data.push( value );

  if( m_min.size() == 0 || value < m_min.top() )
    m_min.push( value );
  else
    m_min.push( m_min.top() );
}

template <typename T> void StackWithMin<T>::pop()
{
  assert( m_data.size() > 0 && m_min.size() > 0 );
  
  m_data.pop();
  m_min.pop();
}

template<typename T> const T& StackWithMin<T>::min() const
{
  assert( m_data.size() > 0 && m_min.size() > 0 );
  
  return m_min.top();
}

template<typename T> T& StackWithMin<T>::top()
{
  return m_data.top();
}

template<typename T> const T& StackWithMin<T>::top() const
{
  return m_data.top();
}

template<typename T> bool StackWithMin<T>::empty() const
{
  return m_data.empty();
}

template<typename T> size_t StackWithMin<T>::size() const
{
  return m_data.size();
}

void Test( const char* testName, const StackWithMin<int>& stack, int expected )
{
  if( testName != NULL )
    printf( "%s begins: ", testName );
  
  if( stack.min() == expected )
    printf( "Passed.\n" );
  else
    printf( "Failed.\n" );
}

int main()
{
  StackWithMin<int> stack;
  
  stack.push( 3 );
  Test( "Test1", stack, 3 );

  stack.push( 4 );
  Test( "Test2", stack, 3 );

  stack.push( 2 );
  Test( "Test3", stack, 2 );

  stack.push( 3 );
  Test( "Test4", stack, 2 );

  stack.pop();
  Test( "Test5", stack, 2 );

  stack.pop();
  Test( "Test6", stack, 3 );

  stack.pop();
  Test( "Test7", stack, 3 );

  stack.push( 0 );
  Test( "Test8", stack, 0 );

}

二12、棧的壓入、彈出序列

      輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否爲該棧的彈出順數組

序。假設壓入棧假設壓入棧的全部數字均不相等。例如序列一、二、3 、四、5是某棧的壓棧序數據結構

列,序列四、五、三、二、1是該壓棧序列對應的一個彈出序列,但四、三、五、一、2就不多是該壓函數

棧序列的彈出序列。測試

#include <iostream>
#include <stdio.h>
#include <stack>

bool IsPopOrder( const int* pPush, const int* pPop, int nLength )
{
  bool bPossible = false;
  
  if( pPush != NULL && pPop != NULL && nLength > 0 )
  {
    const int* pNextPush = pPush;
    const int* pNextPop = pPop;
  
    std::stack<int> stackData;

    while( pNextPop - pPop < nLength )
    {
      while( stackData.empty() || stackData.top() != *pNextPop )
      {
        if( pNextPush - pPush == nLength )
          break;
   
        stackData.push( *pNextPush );
      
        pNextPush++;
      } 
      
      if( stackData.top() != *pNextPop )
        break;

      stackData.pop();
      pNextPop++;
    }

    if( stackData.empty() && pNextPop - pPop == nLength )
      bPossible = true;
  }

  return bPossible;
}

void Test( const char* testName, const int* pPush, const int* pPop, int nLength, bool expected )
{
  if( testName != NULL )
    printf( "%s begins: ", testName );

  if( IsPopOrder( pPush, pPop, nLength ) == expected )
    printf( "Passed.\n" );
  else
    printf( "failed.\n" );
}

void Test1()
{
  const int nLength = 5;
  int push[ nLength ] = { 1, 2, 3, 4, 5 };
  int pop[ nLength ] = { 4, 5, 3, 2, 1 };

  Test( "Test1", push, pop, nLength, true );
}

void Test2()
{
  const int nLength = 5;
  int push[ nLength ] = { 1, 2, 3, 4, 5 };
  int pop[ nLength ] = { 4, 3, 5, 1, 2 };

  Test( "Test2", push, pop, nLength, true );
}

void Test3()
{
  const int nLength = 5;
  int push[ nLength ] = { 1, 2, 3, 4, 5 };
  int pop[ nLength ] = { 3, 5, 4, 1, 2 };

  Test( "Test3", push, pop, nLength, true );
}

void Test4()
{
  const int nLength =1;
  int push[ nLength ] = { 1 };
  int pop[ nLength ] = { 3 };

  Test( "Test4", push, pop, nLength, true );
}

int main()
{
  Test1();
  Test2();
  Test3();
  Test4();

  return 0;
}

二十3、從上往下打印二叉樹

    從上往下打印出二叉樹的每一個結點,同一層的結點按照從左到右的順序打印。ui

#include <iostream>
#include <stdio.h>
#include <deque>

struct BinaryTreeNode
{
  int m_nValue;
  BinaryTreeNode* m_pLeft;
  BinaryTreeNode* m_pRight;
};

BinaryTreeNode* CreateBinaryTreeNode( int value )
{
  BinaryTreeNode* pNode = new BinaryTreeNode();
  pNode->m_nValue = value;
  pNode->m_pLeft = NULL;
  pNode->m_pRight = NULL;

  return pNode;
}

void ConnectTreeNodes( BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight )
{
  if( pParent != NULL )
  {
    pParent->m_pLeft = pLeft;
    pParent->m_pRight = pRight;
  }
}

void PrintTreeNode( BinaryTreeNode* pNode )
{
  if( pNode != NULL )
  {
    printf( "value of this node is: %d\n", pNode->m_nValue );

    if( pNode->m_pLeft != NULL )
      printf( "value of its left child is: %d.\n", pNode->m_pLeft->m_nValue );
    else
      printf( "left child is null.\n" );

    if( pNode->m_pRight != NULL )
      printf( "value of its right child is: %d.\n", pNode->m_pRight->m_nValue );
    else
      printf( "right child is null.\n" );
  }
  else
  {
    printf( "this node is null.\n" );
  }

  printf( "\n" );
}

void PrintTree( BinaryTreeNode* pRoot )
{
  PrintTreeNode( pRoot );

  if( pRoot != NULL )
  {
    if( pRoot->m_pLeft != NULL )
      PrintTree( pRoot->m_pLeft );

    if( pRoot->m_pRight != NULL )
      PrintTree( pRoot->m_pRight );
  }
}

void DestroyTree( BinaryTreeNode* pRoot )
{
  if( pRoot != NULL )
  {
    BinaryTreeNode* pLeft = pRoot->m_pLeft;
    BinaryTreeNode* pRight = pRoot->m_pRight;   

    delete pRoot;
    pRoot = NULL;
  
    DestroyTree( pLeft );
    DestroyTree( pRight );
  }
}

void PrintFromTopToBottom( BinaryTreeNode* pTreeRoot )
{
  if( !pTreeRoot )
    return;

  std::deque<BinaryTreeNode *> dequeTreeNode;
  
  dequeTreeNode.push_back( pTreeRoot );
  
  while( dequeTreeNode.size() )
  {
    BinaryTreeNode *pNode = dequeTreeNode.front();
    dequeTreeNode.pop_front();

    printf( "%d ", pNode->m_nValue );
   
    if( pNode->m_pLeft )
      dequeTreeNode.push_back( pNode->m_pLeft );
    
    if( pNode->m_pRight )
      dequeTreeNode.push_back( pNode->m_pRight );
  }
}

// 測試徹底二叉樹:除了葉子節點,其餘節點都有兩個子節點
//            8
//        6      10
//       5 7    9  11
void Test1()
{
  printf( "\n=====Test1 starts:=====\n" );
  BinaryTreeNode* pNode8 = CreateBinaryTreeNode( 8 );
  BinaryTreeNode* pNode6 = CreateBinaryTreeNode( 6 );
  BinaryTreeNode* pNode10 = CreateBinaryTreeNode( 10 );
  BinaryTreeNode* pNode5 = CreateBinaryTreeNode( 5 );
  BinaryTreeNode* pNode7 = CreateBinaryTreeNode( 7 );
  BinaryTreeNode* pNode9 = CreateBinaryTreeNode( 9 );
  BinaryTreeNode* pNode11 = CreateBinaryTreeNode( 11 );

  ConnectTreeNodes( pNode8, pNode6, pNode10 );
  ConnectTreeNodes( pNode6, pNode5, pNode7 );
  ConnectTreeNodes( pNode10, pNode9, pNode11 );

  PrintTree( pNode8 );

  printf( "\n=====Test1: PrintFromTopToBottom=====\n" );
  PrintFromTopToBottom( pNode8 );

  printf( "\n" );

  DestroyTree( pNode8 );
}

// 測試二叉樹:出葉子結點以外,左右的結點都有且只有一個左子結點
//            8
//          7   
//        6 
//      5
//    4
void Test2()
{
  printf( "\n=====Test2 starts:=====\n" );
  BinaryTreeNode* pNode8 = CreateBinaryTreeNode( 8 );
  BinaryTreeNode* pNode7 = CreateBinaryTreeNode( 7 );
  BinaryTreeNode* pNode6 = CreateBinaryTreeNode( 6 );
  BinaryTreeNode* pNode5 = CreateBinaryTreeNode( 5 );
  BinaryTreeNode* pNode4 = CreateBinaryTreeNode( 4 );

  ConnectTreeNodes( pNode8, pNode7, NULL );
  ConnectTreeNodes( pNode7, pNode6, NULL );
  ConnectTreeNodes( pNode6, pNode5, NULL );
  ConnectTreeNodes( pNode5, pNode4, NULL );

  PrintTree( pNode8 );

  printf( "\n=====Test2: PrintFromTopToBottom=====\n" );
  PrintFromTopToBottom( pNode8 );

  printf( "\n" );

  DestroyTree( pNode8 );
}

int main()
{
  Test1();
  Test2();

  return 0;
}

二十4、二叉搜索樹的後序遍歷

     輸入一個整數數組,判斷該數組是否是某二叉搜索樹的後序遍歷的結果。若是是則返回this

true,不然返回false。假設輸入的數組的任何兩個數字都互不相同。spa

#include <iostream>
#include <stdio.h>

bool VerifySquenceOfBST( int sequence[], int length )
{
  if( sequence == NULL || length <= 0 )
    return false;

  int root = sequence[ length - 1 ];
  
  // 在二叉搜索樹中左子樹的結點小於根節點
  int i = 0;
  for( ; i < length - 1; ++i )
  {
    if( sequence[ i ] > root )
      break;
  }

  // 在二叉搜索樹中右子樹的結點大於根結點
  int j = i;
  for( ; j < length - 1; ++j )
  {
    if( sequence[ j ] < root )
      return false;
  }

  // 判斷左子樹是否是二叉搜索樹
  bool left = true;
  if( i > 0 )
    left = VerifySquenceOfBST( sequence, i );
  
  // 判斷右子樹是否是二叉搜索樹
  bool right = true;
  if( i < length - 1 )
    right = VerifySquenceOfBST( sequence + i, length - i - 1 );

  return ( left && right );
}

void Test( const char* testName, int sequence[], int length, bool expected )
{
  if( testName != NULL )
    printf( "%s begins: ", testName );

  if( VerifySquenceOfBST( sequence, length ) == expected )
    printf( "passed.\n" );
  else
    printf( "failed.\n" );
}

//            10
//         /      \
//        6        14
//       /\        /\
//      4  8     12  16
void Test1()
{
  int data[] = { 4, 8, 6, 12, 16, 14, 10 };
  Test( "Test1", data, sizeof( data ) / sizeof( int ), true );
}

//           5
//          / \
//         4   7
//            /
//           6
void Test2()
{
  int data[] = { 4, 6, 7, 5 };
  Test( "Test2", data, sizeof( data ) / sizeof( int ), true );
}

void Test3()
{
  int data[] = { 7, 4, 6, 5 };
  Test( "Test3", data, sizeof( data ) / sizeof( int ), true );
}

void Test4()
{
    Test( "Test4", NULL, 0, false );
}

int main()
{
  Test1();
  Test2();
  Test3();
  Test4();

  return 0;
}

二十5、二叉樹中和爲某一值的路徑

    輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和爲輸入整數的全部路徑。從樹的根指針

結點開始往下一直到葉結點所通過的結點造成一條路徑。

#include <iostream>
#include <stdio.h>
#include <vector>

struct BinaryTreeNode
{
  int m_nValue;
  BinaryTreeNode* m_pLeft;
  BinaryTreeNode* m_pRight;
};

BinaryTreeNode* CreateBinaryTreeNode( int value )
{
  BinaryTreeNode* pNode = new BinaryTreeNode();
  pNode->m_nValue = value;
  pNode->m_pLeft = NULL;
  pNode->m_pRight = NULL;

  return pNode;
}

void ConnectTreeNodes( BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight )
{
  if( pParent != NULL )
  {
    pParent->m_pLeft = pLeft;
    pParent->m_pRight = pRight;
  }
}

void DestroyTree( BinaryTreeNode* pRoot )
{
  if( pRoot != NULL )
  {
    BinaryTreeNode* pLeft = pRoot->m_pLeft;
    BinaryTreeNode* pRight = pRoot->m_pRight;   

    delete pRoot;
    pRoot = NULL;
  
    DestroyTree( pLeft );
    DestroyTree( pRight );
  }
}

void FindPath( BinaryTreeNode* pRoot, int expectedSum, 
               std::vector<int>& path, int currentSum )
{
  currentSum += pRoot->m_nValue;
  path.push_back( pRoot->m_nValue );

  // 若是是葉結點,而且路徑上結點的和等於輸入的值
  // 打印出這條路徑
  bool isLeaf = pRoot->m_pLeft == NULL && pRoot->m_pRight == NULL;
  if( currentSum == expectedSum && isLeaf )
  {
    printf( "A path is found: " );
    std::vector<int>::iterator iter = path.begin();
    for( ; iter != path.end(); ++iter )
      printf( "%d\t", *iter );
  
    printf( "\n" );
  }

  // 若是不是葉結點,則遍歷它的子結點
  if( pRoot->m_pLeft != NULL )
    FindPath( pRoot->m_pLeft, expectedSum, path, currentSum );
  if( pRoot->m_pRight != NULL )
    FindPath( pRoot->m_pRight, expectedSum, path, currentSum );

  // 在返回到父結點以前,在路徑上刪除當前結點
  path.pop_back();
}


void FindPath( BinaryTreeNode* pRoot, int expectedSum )
{
  if( pRoot == NULL )
    return;
  
  std::vector<int> path;
  int currentSum = 0;
  FindPath( pRoot, expectedSum, path, currentSum );
}

void Test( const char* testName, BinaryTreeNode* pRoot, int expectedSum )
{
  if( testName != NULL )
    printf( "%s begins:\n", testName );

  FindPath( pRoot, expectedSum );

  printf( "\n" );
}

//            10
//         /      \
//        5        12
//       /\        
//      4  7     
// 有兩條路徑上的結點和爲22
void Test1()
{
  BinaryTreeNode* pNode10 = CreateBinaryTreeNode( 10 );
  BinaryTreeNode* pNode5 = CreateBinaryTreeNode( 5 );
  BinaryTreeNode* pNode12 = CreateBinaryTreeNode( 12 );
  BinaryTreeNode* pNode4 = CreateBinaryTreeNode( 4 );
  BinaryTreeNode* pNode7 = CreateBinaryTreeNode( 7 );

  ConnectTreeNodes( pNode10, pNode5, pNode12 );
  ConnectTreeNodes( pNode5, pNode4, pNode7 );

  printf( "Two paths should be found in Test1.\n" );
  Test( "Test1", pNode10, 22 );

  DestroyTree( pNode10 );
}

//            10
//         /      \
//        5        12
//       /\        
//      4  7     
// 有兩條路徑上的結點和爲22
void Test2()
{
  BinaryTreeNode* pNode10 = CreateBinaryTreeNode( 10 );
  BinaryTreeNode* pNode5 = CreateBinaryTreeNode( 5 );
  BinaryTreeNode* pNode12 = CreateBinaryTreeNode( 12 );
  BinaryTreeNode* pNode4 = CreateBinaryTreeNode( 4 );
  BinaryTreeNode* pNode7 = CreateBinaryTreeNode( 7 );

  ConnectTreeNodes( pNode10, pNode5, pNode12 );
  ConnectTreeNodes( pNode5, pNode4, pNode7 );

  printf( "No paths should be found in Test2.\n" );
  Test( "Test2", pNode10, 15 );

  DestroyTree( pNode10 );
}

// 樹中沒有結點
void Test3()
{
  printf( "No paths should be found in Test3.\n" );
  Test( "Test3", NULL, 0 );
}

int main()
{
  Test1();
  Test2();
  Test3();

  return 0;
}

二十6、複雜鏈表的複製

     請實現函數ComplexListNode* Clone( complexListNode* pHead ),複製一個複雜鏈表。在復

雜鏈表中,每一個結點除了有一個m_pNext指針指向下一個結點外,還有一個m_pSibling指向鏈

表中的任意結點或者NULL。

#include <iostream>
#include <stdio.h>

struct ComplexListNode
{
  int m_nValue;
  ComplexListNode* m_pNext;
  ComplexListNode* m_pSibling;
};

ComplexListNode* CreateNode( int nValue )
{
  ComplexListNode* pNode = new ComplexListNode();
  
  pNode->m_nValue = nValue;
  pNode->m_pNext = NULL;
  pNode->m_pSibling = NULL;

  return pNode;
}

void BuildNodes( ComplexListNode* pNode, ComplexListNode* pNext, ComplexListNode* pSibling )
{
  if( pNode != NULL )
  {
    pNode->m_pNext = pNext;
    pNode->m_pSibling = pSibling;
  }
}

void PrintList( ComplexListNode* pHead )
{
  ComplexListNode* pNode = pHead;
  while( pNode != NULL )
  {
    printf( "The value of this node is: %d.\n", pNode->m_nValue );

    if( pNode->m_pSibling != NULL )
      printf( "The value of its sibling is: %d.\n", pNode->m_pSibling->m_nValue );
    else
      printf( "This node does not have a sibling.\n" );

    printf( "\n" );
  
    pNode = pNode->m_pNext;
  }
}

void CloneNodes( ComplexListNode* pHead )
{
  ComplexListNode* pNode = pHead;
  while( pNode != NULL )
  {
    ComplexListNode* pCloned = new ComplexListNode();
    pCloned->m_nValue = pNode->m_nValue;
    pCloned->m_pNext = pNode->m_pNext;
    pCloned->m_pSibling = NULL;

    pNode->m_pNext = pCloned;
  
    pNode = pCloned->m_pNext;
  }
}

void ConnectSiblingNodes( ComplexListNode* pHead )
{
  ComplexListNode* pNode = pHead;
  while( pNode != NULL )
  {
    ComplexListNode* pCloned = pNode->m_pNext;
    if( pNode->m_pSibling != NULL )
    {
      pCloned->m_pSibling = pNode->m_pSibling->m_pNext;
    }

    pNode = pCloned->m_pNext;
  }
}

ComplexListNode* ReconnectNodes( ComplexListNode* pHead )
{
  ComplexListNode* pNode = pHead;
  ComplexListNode* pClonedHead = NULL;
  ComplexListNode* pClonedNode = NULL;

  if( pNode != NULL )
  {
    pClonedHead = pClonedNode = pNode->m_pNext;
    pNode->m_pNext = pClonedNode->m_pNext;
    pNode = pNode->m_pNext; 
  }

  while( pNode != NULL )
  {
    pClonedNode->m_pNext = pNode->m_pNext;
    pClonedNode = pClonedNode->m_pNext;
  
    pNode->m_pNext = pClonedNode->m_pNext;
    pNode = pNode->m_pNext;
  }

  return pClonedHead;
}

ComplexListNode* Clone( ComplexListNode* pHead )
{
  CloneNodes( pHead );
  ConnectSiblingNodes( pHead );
  return ReconnectNodes( pHead );
}

void Test( const char* testName, ComplexListNode* pHead )
{
  if( testName != NULL )
    printf( "%s begins:\n", testName );

  printf( "The original list is:\n" );
  PrintList( pHead );

  ComplexListNode* pClonedHead = Clone( pHead );

  printf( "The cloned list is:\n" );
  PrintList( pClonedHead );
}

//          -----------------
//         \|/              |
//  1-------2-------3-------4-------5
//  |       |      /|\             /|\
//  --------+--------               |
//          -------------------------
void Test1()
{
  ComplexListNode* pNode1 = CreateNode( 1 );
  ComplexListNode* pNode2 = CreateNode( 2 );
  ComplexListNode* pNode3 = CreateNode( 3 );
  ComplexListNode* pNode4 = CreateNode( 4 );
  ComplexListNode* pNode5 = CreateNode( 5 );

  BuildNodes( pNode1, pNode2, pNode3 );
  BuildNodes( pNode2, pNode3, pNode5 );
  BuildNodes( pNode3, pNode4, NULL );
  BuildNodes( pNode4, pNode5, pNode2 );

  Test( "Test1", pNode1 );
}

// 只有一個結點
void Test2()
{
  ComplexListNode* pNode1 = CreateNode( 1 );
  BuildNodes( pNode1, NULL, pNode1 );

  Test( "Test2", pNode1 );
}

int main()
{
  Test1();
  Test2();

  return 0;
}

二十7、二叉搜索樹與雙向鏈表

     輸入一顆二叉搜索樹,將該二叉搜索樹轉化成一個排序的雙向鏈表。要求不能建立任何新的

結點,只能調整樹中結點指針的指向。

#include <iostream>
#include <stdio.h>

struct BinaryTreeNode
{
  int m_nValue;
  BinaryTreeNode* m_pLeft;
  BinaryTreeNode* m_pRight;
};

BinaryTreeNode* CreateBinaryTreeNode( int value )
{
  BinaryTreeNode* pNode = new BinaryTreeNode();
  pNode->m_nValue = value;
  pNode->m_pLeft = NULL;
  pNode->m_pRight = NULL;

  return pNode;
}

void ConnectTreeNodes( BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight )
{
  if( pParent != NULL )
  {
    pParent->m_pLeft = pLeft;
    pParent->m_pRight = pRight;
  }
}

void PrintTreeNode( BinaryTreeNode* pNode )
{
  if( pNode != NULL )
  {
    printf( "value of this node is: %d\n", pNode->m_nValue );

    if( pNode->m_pLeft != NULL )
      printf( "value of its left child is: %d.\n", pNode->m_pLeft->m_nValue );
    else
      printf( "left child is null.\n" );

    if( pNode->m_pRight != NULL )
      printf( "value of its right child is: %d.\n", pNode->m_pRight->m_nValue );
    else
      printf( "right child is null.\n" );
  }
  else
  {
    printf( "this node is null.\n" );
  }

  printf( "\n" );
}

void PrintTree( BinaryTreeNode* pRoot )
{
  PrintTreeNode( pRoot );

  if( pRoot != NULL )
  {
    if( pRoot->m_pLeft != NULL )
      PrintTree( pRoot->m_pLeft );

    if( pRoot->m_pRight != NULL )
      PrintTree( pRoot->m_pRight );
  }
}

void DestroyTree( BinaryTreeNode* pRoot )
{
  if( pRoot != NULL )
  {
    BinaryTreeNode* pLeft = pRoot->m_pLeft;
    BinaryTreeNode* pRight = pRoot->m_pRight;   

    delete pRoot;
    pRoot = NULL;
  
    DestroyTree( pLeft );
    DestroyTree( pRight );
  }
}

void ConvertNode( BinaryTreeNode* pNode, BinaryTreeNode** pLastNodeInList )
{
  if( pNode == NULL )
    return;

  BinaryTreeNode *pCurrent = pNode;
 
  if( pCurrent->m_pLeft != NULL )
    ConvertNode( pCurrent->m_pLeft, pLastNodeInList );

  pCurrent->m_pLeft = *pLastNodeInList;
  if( *pLastNodeInList != NULL )
    ( *pLastNodeInList )->m_pRight = pCurrent;

  *pLastNodeInList = pCurrent;

  if( pCurrent->m_pRight != NULL )
    ConvertNode( pCurrent->m_pRight, pLastNodeInList );
}

BinaryTreeNode* Convert( BinaryTreeNode* pRootOfTree )
{
  BinaryTreeNode *pLastNodeInList = NULL;
  ConvertNode( pRootOfTree, &pLastNodeInList );
  
  // pLastNodeInList指向雙向鏈表的尾結點,須要返回頭文件
  BinaryTreeNode *pHeadOfList = pLastNodeInList;
  while( pHeadOfList != NULL && pHeadOfList->m_pLeft != NULL )
    pHeadOfList = pHeadOfList->m_pLeft;

  return pHeadOfList;
}

void PrintDoubleLinkedList( BinaryTreeNode* pHeadOfList )
{
  BinaryTreeNode* pNode = pHeadOfList;

  printf( "The nodes from left to right are:\n" );
  while( pNode != NULL )
  {
    printf( "%d\t", pNode->m_nValue );

    if( pNode->m_pRight == NULL )
      break;
    pNode = pNode->m_pRight;
  }

  printf( "\nThe nodes from right to left are:\n" );
  while( pNode != NULL )
  {
    printf( "%d\t", pNode->m_nValue );

    if( pNode->m_pLeft == NULL )
      break;
    pNode = pNode->m_pLeft;
  }

  printf( "\n" );
}

void DestroyList( BinaryTreeNode* pHeadOfList )
{
  BinaryTreeNode* pNode = pHeadOfList;
  while( pNode != NULL )
  {
    BinaryTreeNode* pNext = pNode->m_pRight;

    delete pNode;
    pNode = pNext;
  }
}

void Test( const char* testName, BinaryTreeNode* pRootOfTree )
{
  if( testName != NULL )
    printf( "%s begins:\n", testName );

  PrintTree( pRootOfTree );

  BinaryTreeNode* pHeadOfList = Convert( pRootOfTree );

  PrintDoubleLinkedList( pHeadOfList );
}

//            10
//         /      \
//        6        14
//       /\        /\
//      4  8     12  16
void Test1()
{
  BinaryTreeNode* pNode10 = CreateBinaryTreeNode( 10 );
  BinaryTreeNode* pNode6 = CreateBinaryTreeNode( 6 );
  BinaryTreeNode* pNode14 = CreateBinaryTreeNode( 14 );
  BinaryTreeNode* pNode4 = CreateBinaryTreeNode( 4 );
  BinaryTreeNode* pNode8 = CreateBinaryTreeNode( 8 );
  BinaryTreeNode* pNode12 = CreateBinaryTreeNode( 12 );
  BinaryTreeNode* pNode16 = CreateBinaryTreeNode( 16 );

  ConnectTreeNodes( pNode10, pNode6, pNode14 );
  ConnectTreeNodes( pNode6, pNode4, pNode8 );
  ConnectTreeNodes( pNode14, pNode12, pNode16 );

  Test( "Test1", pNode10 );

  DestroyList( pNode4 );	
}

// 樹中只有1個結點
void Test2()
{
  BinaryTreeNode* pNode1 = CreateBinaryTreeNode( 1 );
  Test( "Test2", pNode1 );

  DestroyList( pNode1 );
}

// 樹中沒有結點
void Test3()
{
  Test( "Test3", NULL );
}

int main()
{
  Test1();
  Test2();
  Test3();

  return 0;
}

二十8、字符串的排列

    輸入一個字符串,打印出該字符串中字符的全部排列。例如輸入字符串abc,則打印出由字符

串a、b、c所能列出來的全部字符串abc、bac、bca、cab和cba。

#include <iostream>
#include <stdio.h>

void Permutation( char* pStr, char* pBegin )
{
  if( *pBegin == '\0' )
  {
    printf( "%s\n", pStr );
  }
  else
  {
    for( char* pCh = pBegin; *pCh != '\0'; ++pCh )
    {
      char temp = *pCh;
      *pCh = *pBegin;
      *pBegin = temp;
   
      Permutation( pStr, pBegin + 1 );

      temp = *pCh;
      *pCh = *pBegin;
      *pBegin = temp;
    }
  }
}

void Permutation( char* pStr )
{
  if( pStr == NULL )
    return;
 
  Permutation( pStr, pStr );
}

void Test( char* pStr )
{
  if( pStr == NULL )
    printf( "Test for NULL begins:\n" );
  else
    printf( "Test for %s begins:\n", pStr );

  Permutation( pStr );
  
  printf( "\n" );
}

int main()
{
  Test( NULL );

  char string1[] = "";
  Test( string1 );

  char string2[] = "a";
  Test( string2 );

  char string3[] = "ab";
  Test( string3 );

  char string4[] = "abc";
  Test( string4 );

  return 0;
}

二十9、數組中出現次數超過一半的數字

    數組中有一個數字出現的次數超過數組長度,請找出這個數字。例如輸入一個長度爲9的數組

{ 1, 2, 3,2, 2, 2, 5, 4, 2 }。因爲數字2在數組中出現了5次,超過數組長度的一半,所以輸出2。

#include <iostream>
#include <stdio.h>

bool CheckMoreThanHalf( int* numbers, int length, int number )
{
  int times = 0;
  for( int i = 0; i < length; ++i )
  {
    if( numbers[ i ] == number )
    times++;
  }
 
  bool isMoreThanHalf = true;
  if( times * 2 <= length )
  {
    isMoreThanHalf = false;
  }

  return isMoreThanHalf;
}

int MoreThanHalfNum( int* numbers, int length )
{
  if( numbers == NULL || length <= 0 )
    return 0;

  int result = numbers[ 0 ];
  int times = 1;
  for( int i = 1; i < length; ++i )
  {
    if( times == 0 )
    {
      result = numbers[ i ];
      times = 1;
    }
    else if( numbers[ i ] == result )
      times++;
    else
      times--;
  }
  
  if( !CheckMoreThanHalf( numbers, length, result ) )
    result = 0;

  return result;
}

void Test( const char* testName, int* numbers, int length, int expectedValue, bool expectedFlag )
{
  if( testName != NULL )
    printf( "%s begins: \n", testName );

  int* copy = new int[ length ];
  for( int i = 0; i < length; ++i )
    copy[ i ] = numbers[ i ];

  printf( "Test for solution: " );
  int result = MoreThanHalfNum( copy, length );
  if( result == expectedValue )
    printf("Passed.\n");
  else
    printf("Failed.\n");

  delete[ ] copy;
}

// 存在出現次數超過數組長度一半的數字
void Test1()
{
  int numbers[] = { 1, 2, 3, 2, 2, 2, 5, 4, 2 };
  Test( "Test1", numbers, sizeof( numbers ) / sizeof( int ), 2, false );
}

// 不存在出現次數超過數組長度一半的數字
void Test2()
{
  int numbers[] = { 1, 2, 3, 2, 4, 2, 5, 2, 3 };
  Test( "Test2", numbers, sizeof( numbers ) / sizeof( int ), 0, true );
}

// 只有一個元素的數組
void Test3()
{
   int numbers[] = { 1 };
   Test( "Test3", numbers, 1, 1, false );
}

// 輸入空指針
void Test4()
{
    Test( "Test4", NULL, 0, 0, true );
}

int main()
{
  Test1();
  Test2();
  Test3();
  Test4();

  return 0;
}

三10、最小的K個數

    輸入n個整數,找出其中最小的k個數。找出其中最小的k個數。例如輸入四、五、一、六、二、

七、三、8這8個數字,則最小的4個數字是一、二、三、4。

#include <iostream>
#include <set>
#include <vector>
#include <stdio.h>

using namespace std;

typedef multiset<int, greater<int> > intSet;
typedef multiset<int, greater<int> >::iterator setIterator;

void GetLeastNumbers( const vector<int>& data, intSet& leastNumbers, int k )
{
  leastNumbers.clear();
  
  if( k < 1 || data.size() < k )
    return;

  vector<int>::const_iterator iter = data.begin();

  for( ; iter != data.end(); ++iter )
  {
    if( leastNumbers.size() < k )
      leastNumbers.insert( *iter );

    else
    {
      setIterator iterGreatest = leastNumbers.begin();
   
      if( *iter < *( leastNumbers.begin() ) )
      {
        leastNumbers.erase( iterGreatest );
        leastNumbers.insert( *iter );
      }
    }
  }
}

void Test( const char* testName, int* data, int n, int* expectedResult, int k )
{
  if( testName != NULL )
    printf( "%s begins: \n", testName );

  vector<int> vectorData;
    for( int i = 0; i < n; ++i )
      vectorData.push_back( data[ i ] );

  if( expectedResult == NULL )
    printf( "The input is invalid, we don't expect any result.\n" );
  else
  {
    printf( "Expected result: \n" );
    for( int i = 0; i < k; ++i )
      printf( "%d\t", expectedResult[ i ] );
    printf( "\n" );
  }

  printf( "Result for solution:\n" );
  intSet leastNumbers;
  GetLeastNumbers( vectorData, leastNumbers, k );
  printf( "The actual output numbers are:\n" );
  for( setIterator iter = leastNumbers.begin(); iter != leastNumbers.end(); ++iter )
    printf( "%d\t", *iter );
  printf( "\n\n" );
}

// k小於數組的長度
void Test1()
{
  int data[ ] = { 4, 5, 1, 6, 2, 7, 3, 8 };
  int expected[ ] = { 1, 2, 3, 4} ;
  Test( "Test1", data, sizeof( data ) / sizeof( int ), expected, sizeof( expected ) / sizeof( int ) );
}

// k等於數組的長度
void Test2()
{
  int data[ ] = { 4, 5, 1, 6, 2, 7, 3, 8 };
  int expected[ ] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  Test( "Test2", data, sizeof( data ) / sizeof( int ), expected, sizeof( expected ) / sizeof( int ) );
}

// k大於數組的長度
void Test3()
{
  int data[ ] = { 4, 5, 1, 6, 2, 7, 3, 8 };
  int* expected = NULL;
  Test( "Test3", data, sizeof( data ) / sizeof( int ), expected, 10 );
}

// k等於1
void Test4()
{
  int data[ ] = { 4, 5, 1, 6, 2, 7, 3, 8 };
  int expected[ ] = { 1 };
  Test( "Test4", data, sizeof( data ) / sizeof( int ), expected, sizeof( expected ) / sizeof( int ) );
}

// k等於0
void Test5()
{
  int data[ ] = { 4, 5, 1, 6, 2, 7, 3, 8 };
  int* expected = NULL;
  Test( "Test5", data, sizeof( data ) / sizeof( int ), expected, 0 );
}

// 數組中有相同的數字
void Test6()
{
  int data[ ] = { 4, 5, 1, 6, 2, 7, 2, 8 };
  int expected[ ] = { 1, 2 };
  Test( "Test6", data, sizeof( data ) / sizeof( int ), expected, sizeof( expected ) / sizeof( int ) );
}

// 輸入空指針
void Test7()
{
  int* expected = NULL;
  Test( "Test7", NULL, NULL, expected, 0 );
}

int main()
{
  Test1();
  Test2();
  Test3();
  Test4();
  Test5();
  Test6();
  Test7();

  return 0;
}

相關文章
相關標籤/搜索