文档章节

编程题——21~30

thanatos_y
 thanatos_y
发布于 2016/07/22 17:31
字数 3825
阅读 6
收藏 0

二十一、包含min函数的栈

     定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调

用min、push及pop的时间复杂度都是O(1)。

/*
  定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的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 );

}

二十二、栈的压入、弹出序列

      输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺

序。假设压入栈假设压入栈的所有数字均不相等。例如序列1、2、3 、4、5是某栈的压栈序

列,序列4、5、3、2、1是该压栈序列对应的一个弹出序列,但4、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;
}

二十三、从上往下打印二叉树

    从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。

#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;
}

二十四、二叉搜索树的后序遍历

     输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回

true,否则返回false。假设输入的数组的任何两个数字都互不相同。

#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;
}

二十五、二叉树中和为某一值的路径

    输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根

结点开始往下一直到叶结点所经过的结点形成一条路径。

#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;
}

二十六、复杂链表的复制

     请实现函数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;
}

二十七、二叉搜索树与双向链表

     输入一颗二叉搜索树,将该二叉搜索树转化成一个排序的双向链表。要求不能创建任何新的

结点,只能调整树中结点指针的指向。

#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;
}

二十八、字符串的排列

    输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串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的数组

{ 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;
}

三十、最小的K个数

    输入n个整数,找出其中最小的k个数。找出其中最小的k个数。例如输入4、5、1、6、2、

7、3、8这8个数字,则最小的4个数字是1、2、3、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;
}

© 著作权归作者所有

共有 人打赏支持
thanatos_y
粉丝 7
博文 112
码字总数 315059
作品 0
成都
程序员
私信 提问
老男孩51CTO博客博文列表整理版20170620更新

老男孩51CTO博客博文列表整理版 (本文原自于一道考试题http://oldboy.blog.51cto.com/2561410/1860985) 老男孩教育运维脱产班35期 刘同学 2017-06-14 17:44:41 老男孩的MySQL私房菜新书视频1...

老男孩oldboy
2016/10/14
0
0
建议考前多熟记的知识点(1)(2)《网络工程师软考辅导——3年真题精解与闯关密卷》

建议考前多熟记的知识点《网络工程师软考辅导》(1)~ (2) 参加2014.11.8网络工程师考试的小伙伴们,开考在即,提醒大家静下心来,梳理一下自己的知识框架,扎扎实实打牢基础,才是通关之本。 ...

wg_wg
06/29
0
0
建议考前多熟记的知识点(1)-(3)《系统集成项目管理工程师软考辅导》

2014.11.8项目经理考试的小伙伴们,开考在即,提醒大家静下心来,梳理一下自己的知识框架,扎扎实实打牢基础,才是通关之本。 真诚感谢您的信任与支持!选用《系统集成项目管理工程师软考辅导...

wg_wg
06/29
0
0
冠军奖30万!刘强东搞了个“猪脸识别”比赛,中美两地同时启动(附比赛详细日程及赛题说明)

编辑 | Katerina Donna 润色 | 鸽子 11月6日,由京东金融与红杉资本联合主办的首届“JDD-2017京东金融全球数据探索者大会”在751大罐举行,同时,大会宣布首届“JDD-2017京东金融全球数据探索...

dqcfkyqdxym3f8rb0
2017/11/06
0
0
6个变态的C语言Hello World程序

下面的六个程序片段主要完成这些事情: 输出Hello, World 混乱C语言的源代码 下面的所有程序都可以在GCC下编译通过,只有最后一个需要动用C++的编译器g++才能编程通过。 hello1.c hello2.c ...

酸奶喝不完
2012/09/08
0
5

没有更多内容

加载失败,请刷新页面

加载更多

小白带你认识netty(二)之netty服务端启动(上)

上一章 中的标准netty启动代码中,ServerBootstrap到底是如何启动的呢?这一章我们来瞅下。 server.group(bossGroup, workGroup);server.channel(NioServerSocketChannel.class).optio...

天空小小
57分钟前
2
0
聊聊storm trident batch的分流与聚合

序 本文主要研究一下storm trident batch的分流与聚合 实例 TridentTopology topology = new TridentTopology(); topology.newStream("spout1", spout) .p......

go4it
昨天
3
0
3分钟总结Mybatis别名

1.系统内置别名: 把类型全小写(resultType/paramType) 2.给某个类起别名 2.1 alias=”自定义” <typeAliases> <typeAlias type="com.bjsxt.pojo.People" alias="peo"/> </typeAli......

KingFightingAn
昨天
2
0
JAVA设计模式之模板方法模式和建造者模式

一、前期回顾 上一篇《Java 设计模式之工厂方法模式与抽象工厂模式》介绍了三种工厂模式,分别是工厂方法模式,简单工厂方法模式,抽象工厂模式,文中详细根据实际场景介绍了三种模式的定义,...

木木匠
昨天
8
0
C中的宏的使用(宏嵌套/宏展开/可变参数宏)

基本原则: 在展开当前宏函数时,如果形参有#或##则不进行宏参数的展开,否则先展开宏参数,再展开当前宏。 #是在定义两边加上双引号 #define _TOSTR(s) #sprintf(_TOSTR(test ABC))pr...

SamXIAO
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部