#ifndef _MS_1_
#define _MS_1_
void TestMS_1();
/*
1.把二元查找树转变成排序的双向链表
输入一颗二元查找树,将其转变成一个排序的双向链表,
不能穿件任何新的节点,只能调整指针的指向
双向链表的顺序是按照中序遍历的顺序生成
*/
// 二叉查找树节点
struct TreeNode
{
int num;
TreeNode *left;
TreeNode *right;
TreeNode(int _num, TreeNode *_left = 0, TreeNode *_right = 0) : num(_num), left(_left), right(_right){}
};
// 双向链表节点
struct ListNode
{
int num;
ListNode *pre;
ListNode *next;
ListNode(int _num, ListNode *_pre = 0, ListNode *_next = 0) : num(_num), pre(_pre), next(_next){}
ListNode()
{
ListNode(0);
}
bool operator= (const ListNode & right)
{
if (this == &right)
{
return true;
}
if (this->num == right.num && this->next == right.next)
{
return true;
}
return false;
}
};
void TestBinaryTreeToDoubleList();
ListNode *BinaryTreeToDoubleList(TreeNode *root);
void MiddleSearch(TreeNode *root, ListNode * &pListNode);
void DestroyDbList(ListNode *pDbList);
/*
2.设计包含Min函数的栈
定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素
要求min、push、pop的时间复杂度都是O(1)
这道题做错了!
*/
// 不用数组,用指针
const unsigned DEFAULT_STACK_CAPACITY = 10;
template <typename T>
struct MyStack
{
MyStack();
MyStack(unsigned capacity);
virtual ~MyStack();
void Push(T tmp);
T Pop();
T Top();
bool IsEmpty();
T Min();
T *arr;
// 默认情况下capacity个数最少为4,不够时,翻倍加1
unsigned capacity;
unsigned size;
T min;
};
/*
3:子数组最大和:有正数也有负数
*/
void MaxSubSum(const int *arr, unsigned size, int &sum, unsigned &start, unsigned &end);
void TestMaxSumSum();
/*
4:在二叉树中找出和为某一值的所有路径
输入一个整数和一棵树
从根节点开始往下访问一直到叶节点,所经过的所有节点形成的
一条路径。打印输出所有的路径
*/
// TreeNode已经定义好...
/*
1.搜索:计算以某个节点为根的所有值,然后与num对比
*/
// 以该节点为根,且经过该节点
// 递归计算:先计算子节点,最后一步加上根节点的值, 并将结果保存到result中
// 用堆栈,还好吧...
// 我鄙视用堆栈,自己可以构造干嘛用别人的
// 以后结果不好呈现时,可以考虑用一下堆栈。
// 这里用了个链表,还是用数组吧...
void CalNode(TreeNode *root, int num, ListNode *&result);
void PrintListNode(ListNode *pListNode);
// 数组
void CalNode_2(TreeNode *root, int num, int result[], int count);
void PrintVecInt(int result[], unsigned count);
void TestCalNode();
// 广度优先呢?但是结果不好呈现啊
/*
查找最小的k个元素(数组)
输入一个数组,输出其中的k个最小的元素
*/
// 前k个小元素
void FindKSmallest(int *arr, unsigned start, unsigned end, unsigned k, int *result, unsigned resultSize);
unsigned PivotQuickSort(int *arr, unsigned start, unsigned end, unsigned middle);
void TestFindKSmallest();
/*
上排十个数,在下排给出其出现的次数:
0 1 2 3 4 5 6 7 8 9
6 2 1 0 0 0 1 0 0 0
本来是想考虑其数学特性,看是否能简单给出答案的,看了不行啊
还是用回溯法搜索靠谱啊!!!
*/
bool IsNumOK(int *arr, unsigned size, int *nextArr);
const int NUM_LEN = 9;
// 类似于八皇后的搜索过程
bool FindNextLineNum(int *arr, unsigned size, int *result, unsigned resultSize);
void TestFindNextLineNum();
/*
判断整数序列是不是二叉查找树的后序遍历结果
输入一个数组
*/
// 判断一个数组是不是后序遍历结果:
// 考虑用递归
// 考虑左边、右边。。。
// 我考虑的。。。
bool IsNextBinarySearch(int *arr, unsigned start, unsigned end);
bool IsNextBinarySearch_2(int *arr, unsigned start, unsigned end);
// 判断一个数组是否可能是后序遍历:存在某一个节点,前面的都小于root,后面的都大于root,
// 存在偏树的情况,左偏树返回end-1,右偏树返回start
bool IsMayBeNextBinary(int *arr, unsigned start, unsigned end, unsigned &middle);
void TestIsNextBinarySearch();
/*
翻转句子中单词的顺序,单词内的字符顺序不变
I am a student.-> student. a am I
*/
const int WORD_LEN = 128;
void ReverseWords(char words[][WORD_LEN], unsigned wordNum, char *result);
void ReverseWords_2(const char *str, char *result);
void ParseWord(const char *str, char words[][WORD_LEN], unsigned &wordNum);
void TestReverseWords();
#endif
#include <algorithm>
#include <assert.h>
#include <iostream>
#include <string>
#include "MS_1.h"
using namespace std;
void TestMS_1()
{
TestBinaryTreeToDoubleList();
TestMaxSumSum();
TestCalNode();
TestFindKSmallest();
TestFindNextLineNum();
TestIsNextBinarySearch();
TestReverseWords();
}
void TestBinaryTreeToDoubleList()
{
TreeNode node4(4, 0, 0);
TreeNode node8(8, 0, 0);
TreeNode node6(6, &node4, &node8);
TreeNode node12(12, 0, 0);
TreeNode node16(16, 0, 0);
TreeNode node14(14, &node12, &node16);
TreeNode node10(10, &node6, &node14);
ListNode *dList = BinaryTreeToDoubleList(&node10);
}
ListNode *BinaryTreeToDoubleList(TreeNode *root)
{
// 中序遍历树,每得到一个节点,就新建一个List节点,并挂在
// 链表的末尾
ListNode *dList = 0;
// 以递归的方式中序遍历树
MiddleSearch(root, dList);
while (dList->pre)
{
dList = dList->pre;
}
return dList;
}
void MiddleSearch(TreeNode *root, ListNode * &pListNode)
{
if (!root)
{
return;
}
if (root->left)
{
MiddleSearch(root->left, pListNode);
}
if (!pListNode)
{
pListNode = new ListNode(root->num, 0, 0);
}
else
{
ListNode *pListTmp = new ListNode(root->num, pListNode, 0);
pListNode->next = pListTmp;
pListNode = pListTmp;
}
if (root->right)
{
MiddleSearch(root->right, pListNode);
}
}
void DestroyDbList(ListNode *pDbList)
{
ListNode *pTmp = pDbList;
while (pDbList)
{
pDbList = pDbList->next;
delete pTmp;
pTmp = pDbList;
}
}
// 2:
template <typename T>
MyStack<T>::MyStack()
{
arr = new T[DEFAULT_STACK_CAPACITY];
capacity = DEFAULT_STACK_CAPACITY;
size = 0;
min = T();
}
template <typename T>
MyStack<T>::MyStack(unsigned capa)
{
capacity = capa;
arr = new T[capacity];
size = 0;
min = T();
}
template <typename T>
void MyStack<T>::Push(T tmp)
{
if (size == capacity)
{
capacity = capacity * 2 + 1;
T tmpArr = new T[capacity];
copy(arr, arr + size, tmpArr);
delete arr;
arr = tmpArr;
}
arr[size++] = tmp;
if (tmp < min)
{
min = tmp;
}
}
template <typename T>
T MyStack<T>::Pop()
{
assert(!IsEmpty());
return arr[--size];
}
template <typename T>
T MyStack<T>::Top()
{
assert(!IsEmpty());
return arr[size - 1];
}
template <typename T>
bool MyStack<T>::IsEmpty()
{
return size == 0;
}
template <typename T>
T MyStack<T>::Min()
{
assert(!IsEmpty());
return min;
}
void MaxSubSum(const int *arr, unsigned size, int &sum, unsigned &start, unsigned &end)
{
assert(arr);
sum = 0;
int tmpSum = 0;
sum = 0x80000000;
unsigned tmpStart = 0;
unsigned tmpEnd = 0;
for (unsigned i = 0; i < size; ++i)
{
tmpSum += arr[i];
if (tmpSum < 0)
{
tmpSum = 0;
tmpStart = i + 1;
tmpStart = i + 1;
}
else if (tmpSum >= 0) // 这里要的是最长的!
{
tmpEnd = i;
}
if (tmpSum > sum)
{
sum = tmpSum;
start = tmpStart;
end = tmpEnd;
}
}
}
void TestMaxSumSum()
{
int max = -(1 << 31);
int max2 = 0x80000000;
int max4 = -max2;
int max3 = 1 << 31;
int max5 = 1 << 30;
int max6 = -max5;
}
// 4:
// 深度优先搜索,是否应该广度优先?
void CalNode(TreeNode *root, int num, ListNode *&result)
{
if (!root)
{
return;
}
if (root->num > num)
{
return;
}
else if (root->num == num)
{
PrintListNode(result);
cout << num << " ";
cout << endl;
return;
}
else
{
if (!result)
{
result = new ListNode(root->num, 0, 0);
}
else
{
ListNode *tmp = new ListNode(root->num, result, 0);
result->next = tmp;
result = tmp;
}
if (root->left)
{
CalNode(root->left, num - root->num, result);
}
if (root->right)
{
CalNode(root->right, num - root->num, result);
}
if (result)
{
ListNode *pTmp = result;
result = result->pre;
delete pTmp;
}
}
}
void PrintListNode(ListNode *pListNode)
{
if (pListNode && pListNode->pre)
{
PrintListNode(pListNode->pre);
}
cout << pListNode->num << " ";
}
void TestCalNode()
{
TreeNode node4(4, 0, 0);
TreeNode node7(7, 0, 0);
TreeNode node5(5, &node4, &node7);
TreeNode node12(12, 0, 0);
TreeNode node10(10, &node5, &node12);
ListNode *pList = 0;
CalNode(&node10, 22, pList);
}
void CalNode_2(TreeNode *root, int num, int result[], int count)
{
if (num == 0)
{
PrintVecInt(result, count);
return;
}
else
{
if (!root)
{
return;
}
result[count++] = root->num;
if (root->left)
{
CalNode_2(root->left, num - root->num, result, count);
}
if (root->right)
{
CalNode_2(root->right, num - root->num, result, count);
}
count--;
}
}
void PrintVecInt(int result[], unsigned count)
{
assert(result);
for (unsigned i = 0; i < count; ++i)
{
cout << result[i] << " ";
}
cout << endl;
}
// 算法:O(n),与寻找第K小元素一样
void FindKSmallest(int *arr, unsigned start, unsigned end, unsigned k, int *result, unsigned resultSize)
{
assert(arr && (start <= end));
assert(k <= (end - start + 1));
unsigned middle = start + (end - start) / 2;
// 以middle为pivot排序
unsigned pivot = PivotQuickSort(arr, start, end, middle);
unsigned num = pivot - start + 1;
if (num == k)
{
copy(arr + start, arr + pivot + 1, result + resultSize);
}
else if (num < k)
{
copy(arr + start, arr + pivot + 1, result + resultSize);
resultSize += num;
FindKSmallest(arr, pivot + 1, end, k - num, result, resultSize);
}
else
{
FindKSmallest(arr, start, pivot - 1, k, result, resultSize);
}
}
unsigned PivotQuickSort(int *arr, unsigned start, unsigned end, unsigned middle)
{
assert(arr);
int pivotNum = arr[middle];
unsigned startTmp = start;
swap<int>(arr[start], arr[middle]);
start++;
while(start <= end)
{
while (arr[start] < pivotNum)
{
start++;
}
while (arr[end] > pivotNum)
{
end--;
}
if (start < end)
{
swap<int>(arr[start], arr[end]);
}
}
swap<int>(arr[end], arr[startTmp]);
return end;
}
void TestFindKSmallest()
{
int arr[] = {3, 7, 8, 4, 2, 1, 6, 5};
int result[8];
//FindKSmallest(arr, 0, 7, 4, result, 0);
//FindKSmallest(arr, 0, 7, 2, result, 0);
FindKSmallest(arr, 0, 7, 6, result, 0);
}
/*
上排十个数,在下排给出其出现的次数:
0 1 2 3 4 5 6 7 8 9
6 2 1 0 0 0 1 0 0 0
*/
bool IsNumOK(int *arr, unsigned size, int *nextArr)
{
for (unsigned i = 0; i < size; ++i)
{
unsigned count = 0;
for (unsigned j = 0; j < size; ++j)
{
if (nextArr[j] == arr[i])
{
count++;
}
}
if (nextArr[i] != count)
{
return false;
}
}
return true;
}
bool FindNextLineNum(int *arr, unsigned size, int *result, unsigned resultSize)
{
if (size == resultSize)
{
if (IsNumOK(arr, size, result))
{
PrintVecInt(result, resultSize);
return true;
}
return false;
}
else
{
for (unsigned i = 0; i < NUM_LEN; ++i)
{
result[resultSize] = i;
if (FindNextLineNum(arr, size, result, resultSize + 1))
{
return true;
}
}
}
return false;
}
void TestFindNextLineNum()
{
//int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
int result[10];
if (FindNextLineNum(arr, NUM_LEN, result, 0))
{
cout << "OK" << endl;
}
else
{
cout << "No result" << endl;
}
}
// 判断一个数组是不是后序遍历结果:
bool IsNextBinarySearch(int *arr, unsigned start, unsigned end)
{
// 后序遍历的最后一个一定是父节点
assert(arr);
assert(start <= end);
if (start == end)
{
return true;
}
int node = arr[end];
unsigned middle = end;
unsigned i;
for (i = start; i < end; ++i)
{
if (arr[i] > node)
{
middle = i;
break;
}
}
// 1.middle没被赋值:i == end
// 2.middle == start
for (unsigned j = middle; j < end; ++j)
{
if (arr[j] < node)
{
return false;
}
}
// 说明是左子树 说明第一个就大于,都是右子树
if (i == end || middle == start)
{
return IsNextBinarySearch(arr, start, end - 1);
}
else
{
return ((IsNextBinarySearch(arr, start, middle - 1) &&
IsNextBinarySearch(arr, middle, end - 1)));
}
}
bool IsMayBeNextBinary(int *arr, unsigned start, unsigned end, unsigned &middle)
{
// 遍历两次:第一次找出middle
// 第二次:看middle左右两边的值是否满足条件
int node = arr[end];
return false;
}
bool IsNextBinarySearch_2(int *arr, unsigned start, unsigned end)
{
assert(arr);
assert(start <= end);
int node = arr[end];
unsigned middle = end;
unsigned i;
for (i = start; i < end; ++i)
{
if (arr[i] > node)
{
middle = i;
break;
}
}
// 1.middle没被赋值:i == end
// 2.middle == start
for (unsigned j = middle; j < end; ++j)
{
if (arr[j] < node)
{
return false;
}
}
bool left = true;
if (middle > start)
{
left = IsNextBinarySearch_2(arr, start, middle - 1);
}
bool right = true;
if (middle < end)
{
right = IsNextBinarySearch_2(arr, middle, end - 1);
}
return left && right;
}
void TestIsNextBinarySearch()
{
int arr[] = {5, 7, 6, 9, 11, 10, 8};
//cout << IsNextBinarySearch(arr, 0, 6) << endl;
cout << IsNextBinarySearch_2(arr, 0, 6) << endl;
int arr2[] = {3, 4, 5, 6};
cout << IsNextBinarySearch_2(arr2, 0, 3) << endl;
int arr4[] = {10, 11, 9, 6};
cout << IsNextBinarySearch_2(arr4, 0, 3) << endl;
int arr3[] = {7, 4, 6, 5};
cout << IsNextBinarySearch_2(arr3, 0, 3) << endl;
}
void ReverseWords(char words[][WORD_LEN], unsigned wordNum, char *result)
{
unsigned pos = 0;
for (unsigned i = wordNum; i > 0; --i)
{
//cout << words[i];
strcpy(result + pos, words[i - 1]);
pos += strlen(words[i - 1]);
result[pos++] = ' ';
}
result[pos] = '\0';
}
void ParseWord(const char *str, char words[][WORD_LEN], unsigned &wordNum)
{
wordNum = 0;
unsigned start = 0;
unsigned end = 0;
bool bFlag = false;
unsigned i = 0;
while (*(str + i))
{
if (*(str + i) == ' ')
{
if (bFlag)
{
bFlag = false;
end = i - 1;
strncpy(words[wordNum], str + start, end - start + 1);
words[wordNum++][end - start + 1] = '\0';
}
}
else
{
if (!bFlag)
{
bFlag = true;
start = i;
}
}
++i;
}
strncpy(words[wordNum], str + start, i - start);
words[wordNum++][i - start] = '\0';
}
void TestReverseWords()
{
char *str = " I am a student he is exist OK.";
//char *str = "Ia am";
/*char words[128][WORD_LEN];
unsigned wordNum;
ParseWord(str, words, wordNum);*/
char *result = new char[strlen(str) + 1];
ReverseWords_2(str, result);
cout << result << endl;
delete result;
}
void ReverseWords_2(const char *str, char *result)
{
// 直接一次遍历
unsigned start = 0;
unsigned end = 0;
bool bFlag = false;
unsigned i = 0;
unsigned j = strlen(str);
result[j--] = '\0';
while (*(str + i))
{
if (*(str + i) == ' ')
{
if (bFlag)
{
bFlag = false;
end = i - 1;
j -= end - start;
strncpy(result + j, str + start, end - start + 1);
j--;
}
result[j--] = ' ';
}
else
{
if (!bFlag)
{
bFlag = true;
start = i;
}
}
i++;
}
strncpy(result, str + start, i - start);
}