編程題——11~20

11、數值的整數次方

   實現函數double Power( double base, int exponent ),求base的exponent。不使用哭函數,同時node

不須要考慮大數問題。ios

/*
  實現函數double Power( double base, int exponent ),求base的exponent。不使用哭函數,
  同時不須要考慮大數問題。
*/
#include <iostream>
#include <exception>

int exception_num = 1;

double PowerWithUnsignedExponent( double base, unsigned int exponent )
{
  double result = 1.0;
  for( int i = 1; i <= exponent; i++ )
    result *= base;
  
  return result;
}

bool equal( double num1, double num2 )
{
  if( ( num1 - num2 > -0.000000001 ) && ( num1 - num2 < 0.000000001 ) )
    return true;
  else
    return false;
}

double Power( double base, int exponent )
{
  if( equal( base, 0.0 ) && exponent < 0 )
    throw exception_num;

  unsigned int absExponent = ( unsigned int )( exponent );

  if( exponent < 0 )
    absExponent = ( unsigned int )( -exponent );

  double result = PowerWithUnsignedExponent( base, absExponent );
  if( exponent < 0 )
    result = 1.0 / result;

  return result;
}

// 正常測試
void Test1()
{
  std::cout << " Test1 begins:  " << std::endl;
  double base = 3.2;
  int exponent = 7;
  std::cout << " Power( base, exponent ) = " << Power( base, exponent ) << std::endl;
}

// 指數爲負數測試
void Test2()
{
  std::cout << " Test2 begins:  " << std::endl;
  double base = 3.2;
  int exponent = -7;
  std::cout << " Power( base, exponent ) = " << Power( base, exponent ) << std::endl;
}

// 指數爲零且基數不爲0測試
void Test3()
{
  std::cout << " Test3 begins:  " << std::endl;
  double base = 3.2;
  int exponent = 0;
  std::cout << " Power( base, exponent ) = " << Power( base, exponent ) << std::endl;
}

// 指數爲負且基數爲0測試
void Test4()
{
  std::cout << " Test4 begins:  " << std::endl;
  double base = 0;
  int exponent = -7;
  std::cout << " Power( base, exponent ) = " << Power( base, exponent ) << std::endl;
}

int main()
{
  try
  {
    Test1();
    Test2();
    Test3();
    Test4();
  }
  catch( int exception_num )
  {
    std::cout << " error! base is 0." << std::endl;
  }

  return 0;

}

12、打印1到最大的n位數

      輸入數字n,按順序打印出最大的n位十進制數,好比輸入3,則打印出1,2,3一直到最大的3位git

數即999.數組

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

void PrintNumber( char* number )
{
  bool isBeginning0 = true;
  int nLength = strlen( number );
  
  for( int i = 0; i < nLength; ++i )
  {
    if( isBeginning0 && number[ i ] != '0' )
      isBeginning0 = false;
    if( !isBeginning0 )
    {
      printf( "%c", number[ i ] );
    }
  }

  printf( "\t" );
}

bool Increment( char* number )
{
  bool isOverflow = false;
  int nTakeOver = 0;
  int nLength = strlen( number );

  for( int i = nLength - 1; i >= 0; i-- )
  {
    int nSum = number[ i ] - '0' + nTakeOver;
    if( i == nLength - 1 )
      nSum++;

    if( nSum >= 10 )
    {
      if( i == 0 )
        isOverflow = true;
      else
      {
        nSum -= 10;
        nTakeOver = 1;
        number[ i ] = '0' + nSum;
      }
    }
    else
    {
      number[ i ] = '0' + nSum;
      break;
    }
  }

  return isOverflow;
}

void PrintToMaxOfNDigits( int n )
{
  if( n <= 0 )
    return;
  
  char* number = new char[ n + 1 ];
  memset( number, '0', n );
  number[ n ] = '\0';

  while( !Increment( number ) )
  {
    PrintNumber( number );
  }

  delete [] number;
}

void Test( int n )
{
  printf("Test for %d begins:\n\n", n);

  PrintToMaxOfNDigits( n );
 
  printf( "\n\n" );
  printf("Test for %d ends.\n\n", n);  

}

int main()
{
  Test(1);
  Test(2);
  Test(3);
  Test(0);
  Test(-1);
  
  return 0;
}

十3、在O(1)時間刪除鏈表結點

     給定單向鏈表的頭指針和一個結點指針,定義一個函數在O(1)時間刪除該節點。函數

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

struct ListNode
{
  int m_nValue;
  ListNode* m_pNext;
};

ListNode* CreateListNode( int value )
{
  ListNode* pNode = new ListNode();
  pNode->m_nValue = value;
  pNode->m_pNext = NULL;
  
  return pNode;
}

void ConnectListNodes( ListNode* pCurrent, ListNode* pNext )
{
  if( pCurrent == NULL )
  {
    printf( "Error to connect two nodes.\n" );
    exit( 1 );
  }
  
  pCurrent->m_pNext = pNext;
}

void PrintListNode( ListNode* pNode )
{ 
  if( pNode == NULL )
  {
    printf( "\nThe node is NULL\n" );
  }
  else
  {
    printf( "\nThe key in node is %d.\n", pNode->m_nValue );
  }
}

void PrintList( ListNode* pHead )
{
  printf( "\nPrintList start: \n" );
  ListNode* pNode = pHead;
  while( pNode != NULL )
  {
    printf( "%d\t", pNode->m_nValue );
    pNode = pNode->m_pNext;
  }
}

void DestroyList( ListNode* pHead )
{
  ListNode* pNode = pHead;
  while( pNode != NULL )
  {
    pHead = pHead->m_pNext;
    delete pNode;
    pNode = pHead;
  }
}

void DeleteNode( ListNode** pListHead, ListNode* pToBeDeleted )
{
  if( !pListHead || !pToBeDeleted )
    return;
  
  if( pToBeDeleted->m_pNext != NULL )
  {
    ListNode* pNext = pToBeDeleted->m_pNext;
    pToBeDeleted->m_nValue = pNext->m_nValue;
    pToBeDeleted->m_pNext = pNext->m_pNext;

    delete pNext;
    pNext = NULL;
  }

  else if( *pListHead == pToBeDeleted )
  {
    delete pToBeDeleted;
    pToBeDeleted = NULL;
    *pListHead = NULL;
  }
  
  else
  {
    ListNode* pNode = *pListHead;
    while( pNode->m_pNext != pToBeDeleted )
    {
      pNode = pNode->m_pNext;
    }
    
    pNode->m_pNext = NULL;
    delete pToBeDeleted;
    pToBeDeleted = NULL;
  }
}

void Test( ListNode* pListHead, ListNode* pNode )
{
    printf( "\nThe original list is: \n" );
    PrintList( pListHead );

    printf( "\nThe node to be deleted is: \n" );
    PrintListNode( pNode );

    DeleteNode( &pListHead, pNode );
    
    printf( "\nThe result list is: \n" );
    PrintList( pListHead );
}

// 鏈表中有多個結點,刪除中間的結點
void Test1()
{
  ListNode* pNode1 = CreateListNode( 1 );
  ListNode* pNode2 = CreateListNode( 2 );
  ListNode* pNode3 = CreateListNode( 3 );
  ListNode* pNode4 = CreateListNode( 4 );
  ListNode* pNode5 = CreateListNode( 5 );

  ConnectListNodes( pNode1, pNode2 );
  ConnectListNodes( pNode2, pNode3 );
  ConnectListNodes( pNode3, pNode4 );
  ConnectListNodes( pNode4, pNode5 );

  Test( pNode1, pNode3 );

  DestroyList(pNode1);
}

// 鏈表中有多個結點,刪除尾結點
void Test2()
{
  ListNode* pNode1 = CreateListNode( 1 );
  ListNode* pNode2 = CreateListNode( 2 );
  ListNode* pNode3 = CreateListNode( 3 );
  ListNode* pNode4 = CreateListNode( 4 );
  ListNode* pNode5 = CreateListNode( 5 );

  ConnectListNodes( pNode1, pNode2 );
  ConnectListNodes( pNode2, pNode3 );
  ConnectListNodes( pNode3, pNode4 );
  ConnectListNodes( pNode4, pNode5 );

  Test( pNode1, pNode5 );

  DestroyList( pNode1 );
}

// 鏈表中有多個結點,刪除頭結點
void Test3()
{
  ListNode* pNode1 = CreateListNode( 1 );
  ListNode* pNode2 = CreateListNode( 2 );
  ListNode* pNode3 = CreateListNode( 3 );
  ListNode* pNode4 = CreateListNode( 4 );
  ListNode* pNode5 = CreateListNode( 5 );

  ConnectListNodes( pNode1, pNode2 );
  ConnectListNodes( pNode2, pNode3 );
  ConnectListNodes( pNode3, pNode4 );
  ConnectListNodes( pNode4, pNode5 );

  Test( pNode1, pNode1 );

  DestroyList( pNode1 );
}

// 鏈表中有多個結點,刪除頭結點
void Test4()
{
  ListNode* pNode1 = CreateListNode( 1 );

  Test( pNode1, pNode1 );
}

// 鏈表爲空
void Test5()
{
  Test( NULL, NULL );
}

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

  return 0;
}

十4、調整數組順序使奇數位於偶數前面

      輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得全部奇數位於數組的前測試

半部分,因此偶數位於數組的後半部分。this

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

int exception_num = 1;

void ReorerOddEven( int* pData, unsigned int length )
{
  if( pData == NULL || length <= 0 )
    throw exception_num;

  int *pBegin = pData;
  int *pEnd = pData + length - 1;
  
  while( pBegin < pEnd )
  {
    while( pBegin < pEnd && ( *pBegin & 0x1 ) != 0 )
      pBegin++;

    while( pBegin < pEnd && ( *pEnd & 0x1 ) == 0 )
      pEnd--;

    if( pBegin < pEnd )
    {
      int temp = *pBegin;
      *pBegin = *pEnd;
      *pEnd = temp;
    }
  }

}

void Test1()
{
  int data[] = { 1, 2, 3, 4, 5, 6, 7 };
  unsigned int length = sizeof( data ) / sizeof( int );

  printf("The original array is: \n");
  for( int i = 0; i < length; i++ )
    printf( "%d\t", data[ i ] );
  printf( "\n" );

  ReorerOddEven( data, length );

  printf("The reordered array is: \n");
  for( int i = 0; i < length; i++ )
    printf( "%d\t", data[ i ] );
  printf( "\n" );
}

int main()
{
  try
  {
    Test1();
  }
  catch( ... )
  {
    printf( "invaild input.\n" );
  }
  return 0;
}

十5、鏈表中倒數第k個結點

   輸入一個鏈表,輸出該鏈表中倒數第k個結點。爲了符合大多數人的習慣,本題從1開始計spa

數,即鏈表的尾結點是倒數第1個結點。例如一個鏈表有6個結點,從頭結點開始它們的值依次指針

是一、二、三、四、五、6.這個鏈表的倒數第3個結點是值爲4的結點。code

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

struct ListNode
{
  int m_nValue;
  ListNode* m_pNext;
};

ListNode* CreateListNode( int value )
{
  ListNode* pNode = new ListNode();
  pNode->m_nValue = value;
  pNode->m_pNext = NULL;
  
  return pNode;
}

void ConnectListNodes( ListNode* pCurrent, ListNode* pNext )
{
  if( pCurrent == NULL )
  {
    printf( "Error to connect two nodes.\n" );
    exit( 1 );
  }
  
  pCurrent->m_pNext = pNext;
}

void PrintListNode( ListNode* pNode )
{ 
  if( pNode == NULL )
  {
    printf( "\nThe node is NULL\n" );
  }
  else
  {
    printf( "\nThe key in node is %d.\n", pNode->m_nValue );
  }
}

void PrintList( ListNode* pHead )
{
  printf( "PrintList start: \n" );
  ListNode* pNode = pHead;
  while( pNode != NULL )
  {
    printf( "%d\t", pNode->m_nValue );
    pNode = pNode->m_pNext;
  }
}

void DestroyList( ListNode* pHead )
{
  ListNode* pNode = pHead;
  while( pNode != NULL )
  {
    pHead = pHead->m_pNext;
    delete pNode;
    pNode = pHead;
  }
}


ListNode* FindKthToTail( ListNode* pListHead, unsigned int k )
{
  if( pListHead == NULL || k == 0 )
  {
    return NULL;
  }

  ListNode *pAhead = pListHead;
  ListNode *pBehind = NULL;

  for( unsigned int i = 0; i < k - 1; ++i )
  {
    if( pAhead->m_pNext != NULL )
      pAhead = pAhead->m_pNext;
    else
    {
      return NULL;
    }
  }

  pBehind = pListHead;
  
  while( pAhead->m_pNext != NULL )
  {
    pAhead = pAhead->m_pNext;
    pBehind = pBehind->m_pNext;
  }

  return pBehind;
}

// 測試要找的結點在鏈表中間
void Test1()
{
  printf( "=====Test1 starts:=====\n" );
  ListNode* pNode1 = CreateListNode( 1 );
  ListNode* pNode2 = CreateListNode( 2 );
  ListNode* pNode3 = CreateListNode( 3 );
  ListNode* pNode4 = CreateListNode( 4 );
  ListNode* pNode5 = CreateListNode( 5 );

  ConnectListNodes( pNode1, pNode2 );
  ConnectListNodes( pNode2, pNode3 );
  ConnectListNodes( pNode3, pNode4 );
  ConnectListNodes( pNode4, pNode5 );

  ListNode* pNode = FindKthToTail( pNode1, 2 );
  PrintListNode( pNode );

  DestroyList( pNode1 );
}

// 測試要找的結點是鏈表的尾結點
void Test2()
{
  printf( "=====Test2 starts:=====\n" );
  ListNode* pNode1 = CreateListNode( 1 );
  ListNode* pNode2 = CreateListNode( 2 );
  ListNode* pNode3 = CreateListNode( 3 );
  ListNode* pNode4 = CreateListNode( 4 );
  ListNode* pNode5 = CreateListNode( 5 );

  ConnectListNodes( pNode1, pNode2 );
  ConnectListNodes( pNode2, pNode3 );
  ConnectListNodes( pNode3, pNode4 );
  ConnectListNodes( pNode4, pNode5 );

  ListNode* pNode = FindKthToTail( pNode1, 1 );
  PrintListNode( pNode );

  DestroyList( pNode1 );
}

// 測試要找的結點是鏈表的頭結點
void Test3()
{
  printf( "=====Test3 starts:=====\n" );
  ListNode* pNode1 = CreateListNode( 1 );
  ListNode* pNode2 = CreateListNode( 2 );
  ListNode* pNode3 = CreateListNode( 3 );
  ListNode* pNode4 = CreateListNode( 4 );
  ListNode* pNode5 = CreateListNode( 5 );

  ConnectListNodes( pNode1, pNode2 );
  ConnectListNodes( pNode2, pNode3 );
  ConnectListNodes( pNode3, pNode4 );
  ConnectListNodes( pNode4, pNode5 );

  ListNode* pNode = FindKthToTail( pNode1, 5 );
  PrintListNode( pNode );

  DestroyList( pNode1 );
}

// 測試輸入的第二個參數大於鏈表的結點總數
void Test4()
{
  printf( "=====Test4 starts:=====\n" );
  ListNode* pNode1 = CreateListNode( 1 );
  ListNode* pNode2 = CreateListNode( 2 );
  ListNode* pNode3 = CreateListNode( 3 );
  ListNode* pNode4 = CreateListNode( 4 );
  ListNode* pNode5 = CreateListNode( 5 );

  ConnectListNodes( pNode1, pNode2 );
  ConnectListNodes( pNode2, pNode3 );
  ConnectListNodes( pNode3, pNode4 );
  ConnectListNodes( pNode4, pNode5 );

  ListNode* pNode = FindKthToTail( pNode1, 6 );
  PrintListNode( pNode );

  DestroyList( pNode1 );
}

// 測試輸入的第二個參數爲0
void Test5()
{
  printf( "=====Test5 starts:=====\n" );
  ListNode* pNode1 = CreateListNode( 1 );
  ListNode* pNode2 = CreateListNode( 2 );
  ListNode* pNode3 = CreateListNode( 3 );
  ListNode* pNode4 = CreateListNode( 4 );
  ListNode* pNode5 = CreateListNode( 5 );

  ConnectListNodes( pNode1, pNode2 );
  ConnectListNodes( pNode2, pNode3 );
  ConnectListNodes( pNode3, pNode4 );
  ConnectListNodes( pNode4, pNode5 );

  ListNode* pNode = FindKthToTail( pNode1, 0 );
  PrintListNode( pNode );

  DestroyList( pNode1 );
}


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

  return 0;
}

十6、反轉鏈表

     定義一個函數,輸入一個鏈表的頭結點,反轉該鏈表並輸出反轉後鏈表的頭結點。

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

struct ListNode
{
  int m_nValue;
  ListNode* m_pNext;
};

ListNode* CreateListNode( int value )
{
  ListNode* pNode = new ListNode();
  pNode->m_nValue = value;
  pNode->m_pNext = NULL;

  return pNode;
}

void ConnectListNodes( ListNode* pCurrent, ListNode* pNext )
{
  if( pCurrent == NULL )
  {
    printf( "Error to connect two nodes.\n" );
    exit( 1 );
  }

  pCurrent->m_pNext = pNext;
}

void PrintListNode( ListNode* pNode )
{
  if( pNode == NULL )
  {
    printf( "The node is NULL\n" );
  }
  else
  {
    printf( "The key in node is %d.\n", pNode->m_nValue );
  }
}

void PrintList( ListNode* pHead )
{
  printf( "PrintList start: \n" );
  ListNode* pNode = pHead;
  
  while( pNode != NULL )
  {
    printf( "%d\t", pNode->m_nValue );
    pNode = pNode->m_pNext;
  }
}

void DestroyList( ListNode* pHead )
{
  ListNode* pNode = pHead;
  
  while( pNode != NULL )
  {
    pHead = pHead->m_pNext;
    delete pNode;
    pNode = pHead;
  }
}

ListNode* ReverseList( ListNode* pHead )
{
  ListNode* pReversedHead = NULL;
  ListNode* pNode = pHead;
  ListNode* pPrev = NULL;
  
  while( pNode != NULL )
  {
    ListNode* pNext = pNode->m_pNext;
    
    if( pNext == NULL )
      pReversedHead = pNode;

    pNode->m_pNext = pPrev;
  
    pPrev = pNode;
    pNode = pNext;
  }

  return pReversedHead;
}

ListNode* Test( ListNode* pHead )
{
  printf("\nThe original list is: \n");
  PrintList( pHead );

  ListNode* pReversedHead = ReverseList( pHead );

  printf("\nThe reversed list is: \n");
  PrintList( pReversedHead );

  return pReversedHead;
}

// 輸入的鏈表有多個結點
void Test1()
{
  ListNode* pNode1 = CreateListNode( 1 );
  ListNode* pNode2 = CreateListNode( 2 );
  ListNode* pNode3 = CreateListNode( 3 );
  ListNode* pNode4 = CreateListNode( 4 );
  ListNode* pNode5 = CreateListNode( 5 );

  ConnectListNodes( pNode1, pNode2 );
  ConnectListNodes( pNode2, pNode3 );
  ConnectListNodes( pNode3, pNode4 );
  ConnectListNodes( pNode4, pNode5 );

  ListNode* pReversedHead = Test( pNode1 );

  DestroyList( pReversedHead );
}

// 輸入的鏈表只有一個結點
void Test2()
{
  ListNode* pNode1 = CreateListNode( 1 );

  ListNode* pReversedHead = Test( pNode1 );

  DestroyList( pReversedHead );
}

// 輸入空鏈表
void Test3()
{
  Test( NULL );
}

int main()
{
  Test1();
  Test2();
  Test3();
  
  return 0;
}

十7、合併兩個排序的鏈表

     輸入兩個遞增排序的鏈表,合併這兩個鏈表並使新鏈表中的結點仍然按照遞增排序的。

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

struct ListNode
{
  int m_nValue;
  ListNode* m_pNext;
};

ListNode* CreateListNode( int value )
{
  ListNode* pNode = new ListNode();
  pNode->m_nValue = value;
  pNode->m_pNext = NULL;

  return pNode;
}

void ConnectListNodes( ListNode* pCurrent, ListNode* pNext )
{
  if( pCurrent == NULL )
  {
    printf( "Error to connect two nodes.\n" );
    exit( 1 );
  }

  pCurrent->m_pNext = pNext;
}

void PrintListNode( ListNode* pNode )
{
  if( pNode == NULL )
  {
    printf( "The node is NULL\n" );
  }
  else
  {
    printf( "The key in node is %d.\n", pNode->m_nValue );
  }
}

void PrintList( ListNode* pHead )
{
  printf( "PrintList start: \n" );
  ListNode* pNode = pHead;
  
  while( pNode != NULL )
  {
    printf( "%d\t", pNode->m_nValue );
    pNode = pNode->m_pNext;
  }
}

void DestroyList( ListNode* pHead )
{
  ListNode* pNode = pHead;
  
  while( pNode != NULL )
  {
    pHead = pHead->m_pNext;
    delete pNode;
    pNode = pHead;
  }
}

ListNode* Merge( ListNode* pHead1, ListNode* pHead2 )
{
  if( pHead1 == NULL )
    return pHead2;
  else if( pHead2 == NULL )
    return pHead1;

  ListNode* pMergedHead = NULL;
  
  if( pHead1->m_nValue < pHead2->m_nValue )
  {
    pMergedHead = pHead1;
    pMergedHead->m_pNext = Merge( pHead1->m_pNext, pHead2 );
  }
  else
  {
    pMergedHead = pHead2;
    pMergedHead->m_pNext = Merge( pHead1, pHead2->m_pNext );
  }

  return pMergedHead;
}


ListNode* Test( const char* testName, ListNode* pHead1, ListNode* pHead2 )
{
  if( testName != NULL )
    printf( "%s begins:\n", testName );

  printf( "\nThe first list is:\n" );
  PrintList( pHead1 );

  printf( "\nThe second list is:\n" );
  PrintList( pHead2 );

  printf( "\nThe merged list is:\n" );
  ListNode* pMergedHead = Merge( pHead1, pHead2 );
  PrintList( pMergedHead );
    
  printf("\n\n");

  return pMergedHead;
}

// list1: 1->3->5
// list2: 2->4->6
void Test1()
{
  ListNode* pNode1 = CreateListNode(1);
  ListNode* pNode3 = CreateListNode(3);
  ListNode* pNode5 = CreateListNode(5);

  ConnectListNodes(pNode1, pNode3);
  ConnectListNodes(pNode3, pNode5);

  ListNode* pNode2 = CreateListNode(2);
  ListNode* pNode4 = CreateListNode(4);
  ListNode* pNode6 = CreateListNode(6);

  ConnectListNodes(pNode2, pNode4);
  ConnectListNodes(pNode4, pNode6);

  ListNode* pMergedHead = Test("Test1", pNode1, pNode2);

  DestroyList( pMergedHead );
}

// 鏈表裏有重複數字
// list1: 1->3->5
// list2: 2->3->6
void Test2()
{
  ListNode* pNode1 = CreateListNode(1);
  ListNode* pNode3 = CreateListNode(3);
  ListNode* pNode5 = CreateListNode(5);

  ConnectListNodes(pNode1, pNode3);
  ConnectListNodes(pNode3, pNode5);

  ListNode* pNode2 = CreateListNode(2);
  ListNode* pNode4 = CreateListNode(3);
  ListNode* pNode6 = CreateListNode(6);

  ConnectListNodes(pNode2, pNode4);
  ConnectListNodes(pNode4, pNode6);

  ListNode* pMergedHead = Test("Test2", pNode1, pNode2);

  DestroyList( pMergedHead );
}

// 兩個鏈表都爲空鏈表
// list1: 空鏈表
// list2: 空鏈表
void Test3()
{
  ListNode* pMergedHead = Test( "Test3", NULL, NULL );
}

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

  return 0;
}

十8、樹的子結構

     輸入兩棵樹A和B,判斷B是否是A的子結構。

#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 DestroyTree( BinaryTreeNode* pRoot )
{
  if(pRoot != NULL)
  {
    BinaryTreeNode* pLeft = pRoot->m_pLeft;
    BinaryTreeNode* pRight = pRoot->m_pRight;

    delete pRoot;
    pRoot = NULL;

    DestroyTree( pLeft );
    DestroyTree( pRight );
  }
}

bool DoesTree1HaveTree2( BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2 )
{
  if( pRoot2 == NULL )
    return true;
  
  if( pRoot1 == NULL )
    return false;
  
  if( pRoot1->m_nValue != pRoot2->m_nValue )
    return false;

  return DoesTree1HaveTree2( pRoot1->m_pLeft, pRoot2->m_pLeft ) &&
         DoesTree1HaveTree2(pRoot1->m_pRight, pRoot2->m_pRight);
}


bool HasSubtree( BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2 )
{
  bool result = false;
  
  if( pRoot1 != NULL && pRoot2 != NULL )
  {
    if( pRoot1->m_nValue == pRoot2->m_nValue )
      result = DoesTree1HaveTree2( pRoot1, pRoot2 );
  
    if( !result )
      result = HasSubtree( pRoot1->m_pLeft, pRoot2 );
    
    if( !result )
      result = HasSubtree( pRoot1->m_pRight, pRoot2 );
  }
  
  return result;
}


void Test( const char* testName, BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2, bool expected )
{
  if( HasSubtree( pRoot1, pRoot2 ) == expected )
    printf( "%s passed.\n", testName );
  else
    printf( "%s failed.\n", testName );
}

// 樹中結點含有分叉,樹B是樹A的子結構
//                  8                8
//              /       \           / \
//             8         7         9   2
//           /   \
//          9     2
//               / \
//              4   7
void Test1()
{
  BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode( 8 );
  BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode( 8 );
  BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode( 7 );
  BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode( 9 );
  BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode( 2 );
  BinaryTreeNode* pNodeA6 = CreateBinaryTreeNode( 4 );
  BinaryTreeNode* pNodeA7 = CreateBinaryTreeNode( 7 );

  ConnectTreeNodes( pNodeA1, pNodeA2, pNodeA3 );
  ConnectTreeNodes( pNodeA2, pNodeA4, pNodeA5 );
  ConnectTreeNodes( pNodeA5, pNodeA6, pNodeA7 );

  BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode( 8 );
  BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode( 9 );
  BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode( 2 );

  ConnectTreeNodes( pNodeB1, pNodeB2, pNodeB3 );

  Test("Test1", pNodeA1, pNodeB1, true);

  DestroyTree( pNodeA1 );
  DestroyTree( pNodeB1 );
}

// 樹中結點含有分叉,樹B不是樹A的子結構
//                  8                8
//              /       \           / \
//             8         7         9   2
//           /   \
//          9     3
//               / \
//              4   7
void Test2()
{
  BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode( 8 );
  BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode( 8 );
  BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode( 7 );
  BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode( 9 );
  BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode( 3 );
  BinaryTreeNode* pNodeA6 = CreateBinaryTreeNode( 4 );
  BinaryTreeNode* pNodeA7 = CreateBinaryTreeNode( 7 );

  ConnectTreeNodes( pNodeA1, pNodeA2, pNodeA3 );
  ConnectTreeNodes( pNodeA2, pNodeA4, pNodeA5 );
  ConnectTreeNodes( pNodeA5, pNodeA6, pNodeA7 );

  BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode( 8 );
  BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode( 9 );
  BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode( 2 );

  ConnectTreeNodes( pNodeB1, pNodeB2, pNodeB3 );

  Test( "Test2", pNodeA1, pNodeB1, false );

  DestroyTree( pNodeA1 );
  DestroyTree( pNodeB1 );
}

// 樹A和樹B都爲空
void Test3()
{
    Test( "Test3", NULL, NULL, false );
}

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

  return 0;

}

十9、二叉樹的鏡像

      請完成一個函數,輸入一個二叉樹,該函數輸出它的鏡像。

#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 MirrorRecursively( BinaryTreeNode* pNode )
{
  if( pNode == NULL )
    return;
  if( pNode->m_pLeft == NULL && pNode->m_pRight == NULL )
    return;

  BinaryTreeNode *pTemp = pNode->m_pLeft;
  pNode->m_pLeft = pNode->m_pRight;
  pNode->m_pRight = pTemp;

  if( pNode->m_pLeft )
    MirrorRecursively( pNode->m_pLeft );
  if( pNode->m_pRight )
    MirrorRecursively( 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: MirrorRecursively=====\n" );
  MirrorRecursively( pNode8 );
  PrintTree( pNode8 );

  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: MirrorRecursively=====\n" );
  MirrorRecursively( pNode8 );
  PrintTree( pNode8 );

  DestroyTree( pNode8 );
}

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

  return 0;
}

二10、順時針打印矩陣

     輸入一個矩陣,按照從外向裏以順時針的順序依次打印打印出每一個數字。

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

void printNumber( int number )
{
  printf( "%d\t", number );
}

void PrintMatrixInCircle( int** data, int columns, int rows, int start )
{
  int endX = columns - 1 - start;
  int endY = rows - 1 - start;

  // 從左到右打印一行
  for( int i = start; i <= endX; ++i )
  {
    int number = data[ start ][ i ];
    printNumber( number );  
  }
  
  // 從上到下打印一列
  if( start < endY )
  {
    for( int i = start + 1; i <= endY; ++i )
    {
      int number = data[ i ][ endX ];
      printNumber( number );  
    }  
  }

  // 從右到左打印一行
  if( start < endX && start < endY )
  {
    for( int i = endX - 1; i >= start; --i )
    {
      int number = data[ endY ][ i ];
      printNumber( number );
    }
  }

  // 從下到上打印一列
  if( start < endX && start < endY - 1 )
  {
    for( int i = endY - 1; i >= start + 1; --i )
    {
      int number = data[ i ][ start ];
      printNumber( number );  
    }
  }
}

void PrintMatrixClockwisely( int** data, int columns, int rows )
{
  if( data == NULL || columns <= 0 || rows <= 0 )
    return;

  int start = 0;
  
  while( columns > start * 2 && rows > start * 2 )
  {
    PrintMatrixInCircle( data, columns, rows, start );
    ++start;
  }
}

void Test( int columns, int rows )
{
  printf( "Test Begin: %d columns, %d rows.\n", columns, rows );

  if( columns < 1 || rows < 1 )
    return;

  int** numbers = new int*[ rows ];
  for( int i = 0; i < rows; ++i )
  {
    numbers[ i ] = new int[ columns ];
    for( int j = 0; j < columns; ++j )
    {
      numbers[ i ][ j ] = i * columns + j + 1;
    }
  }

  PrintMatrixClockwisely( numbers, columns, rows );
  printf( "\n" );

  for( int i = 0; i < rows; ++i )
    delete[ ] ( int* )numbers[ i ];

  delete[ ] numbers;
}

int main()
{
  Test(2, 2);
  Test(4, 4);

  return 0;
}

相關文章
相關標籤/搜索