C++常考算法
1 strcpy,
char * strcpy(char* target, char* source)
{ // 不返回const char*, 因为如果用strlen(strcpy(xx,xxx)),类型不匹配。
assert(source != NULL && target != NULL);
char* p = target;
while ((*target++ = *source++) != '\0') // 先赋值,然后用表达式和‘\0’比较,最后指针加1
;
return p; // 这个算法有可能出现地址被覆盖的情况
}
source 拷贝的时候,就把自己的后部分给覆盖了,当source < target && soure + strlen -1 >target时候会出现这种情况。
防止覆盖的解决方案是倒拷贝。(分两种情况处理: 正常情况,和倒着拷贝。)
strcat
char *Strcat(char *pszDest, const char* pszSrc)
{char* p = pszDest;
while(*pszDest) pszDest++;
while((*pszDest++ = *pszSrc++));
return p;
}
2 String 的默认函数
Mystring::Mystring(const char *str)
{
if (NULL == str)
{
m_data = new char[1];
m_data[0] = '\0';
}
else
{
m_data = new char[strlen(str) + 1];
strcpy_s(m_data,strlen(str)+1, str);
}
}
Mystring::~Mystring()
{
delete[] m_data;
}
Mystring::Mystring(const Mystring &another)
{
m_data = new char[strlen(another.m_data) + 1];
strcpy_s(m_data,strlen(another.m_data)+1 ,another.m_data);
}
const Mystring& Mystring::operator=(const Mystring &rhs)
{
if (this == &rhs)
return *this;
delete []m_data;
m_data = new char[strlen(rhs.m_data) + 1];
strcpy_s(m_data,strlen(rhs.m_data) + 1,rhs.m_data);
return *this;
}
3 链表逆置
typedef struct Node
{
int data;
Node *next;
}LinkedNode, *LinkedList;
void reversse(LinkedList &head)
{
if(head == NULL || head->Next == NULL)
return;
LinkedList p = head->next;
LinkedList q = NULL;
head->next = NULL;
while(p)
{ q = q->next;
p->next = head;
head = p;
p = q;
}
head = p;
}
4 有序链表合并,用递归和非递归
递归:每次从当前节点选一个进入合并的链表,对余下的再合并。
LinkedList ListMerge(LinkedNode* p1, LinkedNode *p2)
{
if (p1 == NULL)
return p2;
if (p2 == NULL)
return p1;
LinkedList head = NULL;
if (p1->next < p2->next)
{ head = p1;
head->next = ListMerge(p1->next, p2);
}
else
{head = p2;
head->next = ListMerge(p1, p2->next)
}
return head;
}
非递归:
LinkedList ListMerge2(LinkedNode *p1, LinkedNode *p2)
{
LinkedList head = NULL;
LinkedList p = NULL;
if (p1->data < p2->data)
{
head = p1;
p1 = p1->next;
}
else
{
head = p2;
p2 = p2->next;
}
p = head;
while (p1 != NULL && p2 != NULL)
{
if (p1->data < p2->data)
{
p->next = p1; p1 = p1->next;
}
else
{
p->next = p2; p2 = p2->next;
}
p = p->next;
}
if (p1 != NULL)
p->next = p1;
else
p->next = p2;
return head;
}
5 写一个函数找出一个整数数组中,第二大的数
template<class T>
T secondMax(vector<T> v)
{
int max = 0; //最大值下标
int second = 0; // 第二大值下标
for (int i = 0; i < v.size; i++)
{
if (v[i] > v[max])
{ max = i;
second = max;
}
else if (v[i] < v[max] && v[i] > v[second])
second = i;
}
reutrn second;
}
6 判断单链表是否有环? 如果有,环的长度?第一个环上的点在哪?
判断有环:两个 指针,一个步长是1,另一个步长是2,如果有环的话,二者遍历会相交。
环的长度:相交的点一定在环上,那么从这个交点开始遍历,记录遍历长度,再回来时就得到长度。
第一个环上的点:还是找到相交的那个点,参考下一个问题的答案。
7 判断两个链表是否有交点? 第一个交点在哪?
判断是否相交:把其中一个链表的头尾连接,判断是否有环。
第一个交点: 得到两个链表的长度,求得长度差K,然后长的那个先走K步,然后一起走,第一个交点就是。
8 二分查找
int BinarySearch(int *array, int aSize, int key) // 从长度为aSize的数组array找到等于key的记录,array有序
{
if (array == NULL || aSize <= 0)
return -1;
int low = 0;
int high = aSize - 1;
int mid = 0;
while (low <= high)
{
mid = (low + high) / 2;
if (key > array[mid])
low = mid + 1;
else
if (key < array[mid])
high = mid - 1;
else
return mid;
}
return -1;
}
9 冒泡排序
void bubbleSort(int *array, int len)
{
for (int i = 0; i < len ; i++ )
for (int j = 0; j < len - i-1; j++)
{
if (array[j] > array[j + 1])
swap(array[j], array[j + 1]);
}
}
10 直接插入排序
void insert(int *array, int len)
{
for (int i = 1; i < len; i++)
{
int temp = array[i];
for(int j = i-1; j > 0; j--)
{
if(temp < array[]j);
array[j+1] = array[j];
}
}
}
11 希尔排序
不稳定的排序,平均时间复杂度是nlogn, 保证最后的步长是1. 直接插入排序,每次移动一个位置,希尔排序大步伐的移动。
12 直接选择排序
void select(int *arrya, int len)
{
for (int i = 0; i < len; i++)
{
int min = array[i];
int index = i;
for(int j = i + 1; j < len; j++)
{ if (array[j] < min)
{
min = array[j];
index = j;
}
}
if (i != index)
swap(array[i], array[index]);
}
}
13 快速排序
int quickSort(int *array, int low, int high)
{
if(low == high) return;
int begi = low;
int end = high;
int piv = array[low]
while(low < high)
{ while(high > low && array[high] >piv)
high--;
if (low < high) array[low] = arrray[high];
while(hgih > low && array[low] < piv)
low++;
if(low < high) array[high] = array[low];
}
array[low] = piv;
quickSort(array, begin, low -1);
quickSort(array, high-1, end);
}
14 输入一个数组,实现一个函数,让所有奇数都在偶数前面:
答案:一次快排解决问题.
15 归并排序
void merge_sort(int *data, int start, int end, int *result)
{ if(end == start) return
if (end - start == 1) //区间只有2个元素
{
if(data[start] > data[end])
{
int temp = data[start];
data[start] = data[end];
data[end] = temp;
}
}
else // 继续进行划分
{ merge_sort(data, start, (end-star+1)/2 + start, result);
merge_sort(data, (end-start+1)/2 + start +1, end, result);
merge(data, start, end, result); // 把两个有序的列 归并到 result中。
for(int i = start; i <= end; i++)
data[i] = result[i];
}
}
void merge(int *data,int start,int end,int *result) // start到end这一段中,前半部分有序,后半部分有序,
// 归并到result中。
{
int left_length = (end-sart + 1)/2 +1;
int lef_index = start;
int right_index = start +left_length;
int result_index = start;
while(left_index < start + left_length && right_index < end +1)
{
if(data[left_index] <= data[right_index])
resutl[result_index++] = data[left_index++];
else
result[result_index++] = data[right_index++];
}
while(left_index < start +left_lenght)
result[result_index++] = data[left_index++];
while(right_indx < end + 1)
result[result_index++]=data[right_index++];
}
merge_sort(data,0,length-1,result); // result是格外的存储空间
15 堆排序
16 前序,中序, 后序遍历二叉树的非递归
17 KMP算法