《剑指offer》练习

3二维数组查找

#include<stdio.h>

typedef int ElemType[][4];

// 二维数组matrix中,每一行都从左到右递增排序,
// 每一列都从上到下递增排序
bool find(ElemType r,int rows,int cols,int key){
	bool isFound = false;
	if(r!=NULL && rows>0 && cols>0){//检查参数是否合法 
		int row = 0;
		int col = cols - 1; 
		while(row<rows && col>=0){//循环最后的终止条件 
			if(r[row][col] == key){//命中 
				isFound = true;
				printf("命中\n");
				break;
			}else if(r[row][col]>key){//如果这一列最小值都比key大那么消除该列 
				col--;
			}else{
				row++;//如果改行的最大值都比key小那么消除该行	
			}
		} 
	}
	return isFound; 
}

//  1   2   8   9
//  2   4   9   12
//  4   7   10  13
//  6   8   11  15
// 要查找的数在数组中
int main(){
	int key = 50; 
	ElemType r = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
	bool isFound = find(r,4,4,key);
	printf("查找%d是否查找到:%3d\n",key,isFound);
	return 0;
} 

4替换空格

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

//把字符串中的空格替换成%20,在原字符串的基础上进行替换改变原来的值 
//思路:从后向前替换:原尾指针、新尾指针->逐个后移->如果为空格新尾指针向前移动3个位置 
//时间复杂度:O(n) 
void replaceBlank(char string[]){
	if(string == NULL){  //参数判断 
		return ;
	} 
	
	int originalLength,newLength;//original字符串原长度,newLength替换后的字符串长度 
	int numberofBlank=0;//字符串中空格的个数 
	int indexofOriginal,indexofNew; //原字符串中的最后一个指针位置,新字符串中最后一个字符串的位置 
	originalLength = newLength = indexofOriginal = indexofNew = 0;//初始化变量 
	int i = 0;
	
	while(string[i] != '\0'){ 
		if(string[i] == ' '){
			numberofBlank++; //计算字符串中空格字符的个数 
		}
		originalLength++;//计算源字符串的长度 
		i++;
	}
	if(originalLength <= 0){ //进行长度过滤 
		return ;
	}  
	newLength = originalLength + 2 * numberofBlank; //新字符串的长度  
	indexofOriginal = originalLength;
	indexofNew = newLength;
 	while(originalLength>=0 && indexofNew>indexofOriginal){
		if(string[indexofOriginal] == ' '){//如果为空格新尾指针前移3三个位置 
			string[indexofNew--] = '0'; 
			string[indexofNew--] = '2'; 
			string[indexofNew--] = '%'; 
		} else{
			string[indexofNew--] = string[indexofOriginal];//正常字符逐位后移 
		}	
		indexofOriginal--;//原尾指针每次向前移动一位 
 	}	 	
} 

// 打印
void print(char string[]){
	int i= 0;
	while(string[i] != '\0'){
		printf("%c",string[i]); 
		i++;
	} 
	printf("\n");
} 

int main(){
	char string[] = "I am a luckly boy!";
	printf("进行空格替换前:");
	print(string); 
	printf("进行替换空格后:");
	replaceBlank(string);
	print(string); 

	return 0;
} 

5从尾到头打印链表

#include<stdio.h>
#include<Stack>//引入栈 
using namespace std;//用栈文件必须使用命名空间 

//定义链表结构
typedef struct Node{
	int data;
	struct Node *next;
} Node,*P_Node;
//打印
void print(P_Node L){
	P_Node p = L->next;
	while(p){
		printf("%3d",p->data);
		p = p->next;
	} 
	printf("\n");
} 
//初始化
void init(P_Node &L){
	L = (P_Node)malloc(sizeof(Node));
	if(L == NULL){
		printf("初始化失败\n");
		return ; 
	}
	L->data = 0;
	L->next = NULL;
} 
//创建链表
void createTail(P_Node L,int n) {
	int i = 0;
	P_Node r = L;
	for(i=0;i<n;i++){
		P_Node newNode = (P_Node)malloc(sizeof(Node));
		if(newNode == NULL){
			printf("创建链表失败\n");
			return ;
		}
		newNode->data = i+1;
		newNode->next = r->next;
		r->next = newNode;
		r = newNode;
		L->data++; 
	}
	printf("链表创建成功!\n"); 
}


//使用栈——从尾到头打印链表
void reserve1(P_Node L){
	stack<P_Node> Stack;
	P_Node p = L->next;
	while(p){
		Stack.push(p);
		p = p->next;
	}
	while(!Stack.empty()){
		p = Stack.top();
		Stack.pop();
		printf("%3d",p->data);
	}
	printf("\n");
} 
//使用递归——从尾到头打印链表
void reserve2(P_Node p){
	if(p != NULL){
		if(p->next != NULL){
			reserve2(p->next);
		}
		printf("%3d",p->data);
	}
} 

int main(){
	P_Node L;
	int n = 5;
	init(L);
	createTail(L,n); 
	print(L); 
	
	//从尾到头输出
	reserve1(L); //用栈
	reserve2(L->next); //用递归 
 	printf("\n");
 	
	return 0;
}
 

8旋转数组中的最小值

#include<stdio.h>
typedef int ElemType[5];
//打印
void print(ElemType r,int n){
	int i = 0;
	for(i=0;i<n;i++){
		printf("%3d",r[i]); 
	} 
	printf("\n");
} 
//顺序查找
void minInOrder(ElemType r,int indexPre,int indexAfter) {
	int i = 0;
	int min = r[indexPre];
	for(i = indexPre;i<=indexAfter;i++){
		if(r[i]<min){
			min = r[i];
			break;
		}
	} 
	printf("该旋转数组中的最小值是:%d在第%d位置上\n",min,i+1);
}
//查找旋转数组中的最小值
void min(ElemType r,int length){
	int indexPre,indexAfter,indexMid;
	indexPre = 0;
	indexAfter = length-1;
	indexMid = indexPre; //此处和while中的条件是为了应对数组旋转数量为0即没有任何旋转 r[] = {1,2,3,4,5} 
	while(r[indexPre]>=r[indexAfter]){
		if(indexAfter-indexPre == 1){
			indexMid = indexAfter;
		}
		indexMid = (indexPre+indexAfter)/2;
		//如果indexPre、idnexAfter、indeMid三个数相等时,则必须用顺序查找
		if(r[indexPre] == r[indexAfter] && r[indexPre] == r[indexMid]){
			minInOrder(r,indexPre,indexAfter);
			return ;
		}
		if(r[indexMid]>=r[indexPre]){
			indexPre = indexMid;
		}else if(r[indexMid]<=r[indexAfter]){
			indexAfter = indexMid;
		}
	} 
	printf("该旋转数组中的最小值是:%d在第%d位置上\n",r[indexMid],indexMid+1); 
} 



//计算从1加到n;
//递归实现1+2+3..+n;
int add1(int n){
	return (n<=0) ? 0 : n+add1(n-1); 
} 
//遍历实现1+2+3...+n;
int add2(int n){
	int i =1;
	int result = 0; 
	for(i=1;i<=n;i++){
		result  = result + i;
	} 
	return result;
} 
int main(){
	int n = 5;
	ElemType r = {2,3,4,5,1}; //测试特例:r[] = {1,0,1,1,1};r[] = {1,1,1,0,1}; 
	print(r,n);
	min(r,n);		
	printf("旋转数组中的最小值!\n");
	
	
	printf("\n\n");
	n = 100;
	printf("递归实现:1+2+3...+n = %3d\n",add1(n)); //递归 
	printf("遍历实现:1+2+3...+n = %3d\n",add2(n)); //遍历 
	
	
	return 0;
} 

11数值的整数次方

#include<stdio.h>

double getPower(double base,unsigned int ex){
	if(ex == 0)return 1.0;
	if(ex == 1)return base;
	double result = getPower(base,ex>>1);//这里使用左移一位代替除2操作 
	result = result*result;  //result^2,对计算的结构在进行平方操作
	if(ex & 0x1 == 1){//这里使用了与运算来代替%取余运算 
		result = result * base; //如果ex实奇数则最后再乘以一个base 
	} 
	return result; 
} 

//求数值的整数次方
double power(double base,unsigned int ex){
	
	if(base == 0.0){ //如果base为0则结果为0; 
		return 0.0;
	}
	unsigned int ex_bak = (unsigned int)(ex);
	if(ex<0){ 
		ex_bak = (unsigned int) (-ex);//注意此处无符号整数取负数 
	} 
	double result = getPower(base,ex_bak);
	if(ex<0){
		result = 1.0/result;//如果指数是负数则进行倒数 
	} 
	return result;		
}


int main(){
	double base  = -2;
	unsigned int ex =10  ;
	printf("%lf的%u次方为:%lf\n",base,ex,power(base,ex));
	
	return 0;
} 

14调整数组顺序奇数位于偶数前面

#include<stdio.h>

//定义结构体 
typedef int ElemType[5];

//打印
void print(ElemType r,int length){
	int i =0;
	for(i=0;i<length;i++){
		printf("%3d",r[i]);
	} 
	printf("\n");
} 

//重新定位位置,是奇数位于偶数的前面 
void ReOrder(ElemType r,int length){
	if(r==NULL || length<=0){
		return ;
	}
	int indexPre = 0;
	int indexAfter = length-1;
	while(indexPre<indexAfter){
		while(indexPre<indexAfter && (r[indexPre]&0x1) == 1)indexPre++; //使用&运算符是注意要加上括号,优先级问题  
		while(indexPre<indexAfter && (r[indexAfter]&0x1) != 1)indexAfter--;
		if(indexPre<indexAfter){
			int tmp = r[indexPre];
			r[indexPre] = r[indexAfter];
			r[indexAfter] = tmp;
		}
	}
}

int main(){
	int n = 5;
	ElemType r ={1,2,3,4,5}; 
	print(r,n);
	ReOrder(r,5);
	print(r,n); 
	printf("调整数组顺序是奇数位于偶数前面!\n"); 
	return 0;
} 

15链表中倒数第k个节点

#include<stdio.h>
#include<stdlib.h>
//定义链表结构 
typedef struct Node{
	int data;
	struct Node *next;
}Node,*P_Node; 
//打印
void print(P_Node L){
	P_Node p = L->next;
	while(p){
		printf("%3d",p->data);
		p = p->next;
	}
	printf("\n");
} 
//初始化
void init(P_Node &L){
	L  = (P_Node)malloc(sizeof(Node));
	if(L == NULL){
		printf("初始化失败!\n");
		return ;
	}
	L->data = 0;
	L->next = NULL; 
	printf("初始化成功!\n");
} 
//创建单链表
void createTail(P_Node L,int n ){
	int i = 0; 
	P_Node r = L;
	for(i=0;i<n;i++){
		P_Node newNode = (P_Node)malloc(sizeof(Node));
		if(newNode == NULL){
			printf("创建失败!\n");
			return ;
		}
		newNode->data = i+1;
		newNode->next = r->next;
		r->next = newNode;
		r = newNode;
		L->data++;
	}
	printf("创建成功!\n");
} 
//找到倒数第K个节点
void find(P_Node L,int k){
	int i = 0;
	if(L == NULL || L->next == NULL || k <= 0){//判断链表是否为空
		return ;
	} 
	P_Node fast = L->next;	
	P_Node slow = L->next;
	for(i=1;i<k;i++){ 
		if(fast->next != NULL){//判断k是否大于链表的长度 
			fast = fast->next;
		}else{
			return ;
		}	
	}
	while(fast->next != NULL){ //快的和慢的一块移动,么次移动一个位置。 
		fast = fast->next;
		slow = slow->next;
	} 
	printf("链表中倒数第%d个位置是:%3d\n",k,slow->data); 
} 
//查找链表的中间节点(节点数为偶数时候,取中间两个中的任意一个) 
void findMid(P_Node L){
	if(L == NULL || L->next == NULL){
		return ;
	} 
	P_Node fast,slow;//快指针一次走两步,慢指针一次走一步,当快指针走到尾部时慢指针的位置就是链表中的中间位置, 
	fast = slow = L->next;//开始时候快指针和慢指针都在第一个结点的位置
	
	while(fast->next!= NULL && fast->next->next != NULL){ 
		fast = fast->next->next;
		slow = slow->next; 
	}
	printf("链表的中间节点是:%3d\n",slow->data);
}
//判断链表中是否又环
void ajustRing(P_Node L){
	if(L==NULL || L->next == NULL){ //参数过滤 
		return ;
	} 
	P_Node fast,slow;
	fast = slow = L->next;
	while(fast->next != slow && fast->next != NULL){
		fast = fast->next->next;
		slow = slow;
	}
	printf("该链表中存在环!\n");
} 
int main(){
	int n = 9;
	int k = 3 ;
	P_Node L;
	init(L);
	createTail(L,n);
	print(L);
	find(L,k);//查找链表中倒数第K个节点
	findMid(NULL); //查找链表中的中间节点 
	ajustRing(L);
	
	

	return 0;
} 

16反转链表

#include<stdio.h>
#include<stdlib.h>
//定义结构体
typedef struct Node{
	int data;
	struct Node *next;
} Node,*P_Node;
//打印
void print(P_Node L){
	if(L == NULL){
		return ;
	}
 	P_Node p = L->next;
    while(p != NULL){
        printf("%3d",p->data);
        p = p->next;
    }       
    printf("\n"); 
}
//初始化
void init(P_Node &L){
	if(L == NULL){
		return ;
	}
	L = (P_Node)malloc(sizeof(Node));
	if(L == NULL){
		printf("初始化失败\n");
		return ;
	}
	L->data = 0;
	L->next = NULL;
	printf("初始化成功!\n"); 
} 
//创建链表
void createTail(P_Node L, int n){
	if(L == NULL){
		return ;
	}
	int i = 0;
	P_Node r,newNode;
	r = L; 
	for(i=0;i<n;i++){
		newNode = (P_Node)malloc(sizeof(Node));
	 	if(newNode == NULL){
	 		printf("创建链表失败!\n");
	 		return ;
	 	}
	 	newNode->data = i+1;
		newNode->next = r->next;
		r->next = newNode;
		r = newNode;
		
		L->data++; 
	}
	printf("链表创建成功!\n"); 
} 
//反转链表
void reverse(P_Node L){
	if(L == NULL){
		return;
	}
	P_Node preNode,curNode,nextNode;
	preNode = L->next;
	curNode = preNode->next;
	while(curNode!=NULL){
		nextNode = curNode->next;
		curNode->next = preNode;
		preNode = curNode;
		curNode = nextNode;
	} 
	L->next->next = NULL;
	L->next = preNode;
} 
int main(){
	int n = 10;
	P_Node L;
	init(L);//初始化 
	createTail(L,n);
	print(L);
	reverse(L); //反转链表 
	print(L);
	//printf("反转链表!\n");
	return 0;
} 

17合并两个排序链表

#include<stdio.h>
#include<stdlib.h>
//定义结构体
typedef struct Node{
	int data;
	struct Node *next;
} Node,*P_Node;
//打印
void print(P_Node L){
	if(L == NULL){
		return ;
	}
 	P_Node p = L->next;
    while(p != NULL){
        printf("%3d",p->data);
        p = p->next;
    }       
    printf("\n"); 
}
//初始化
void init(P_Node &L){
	if(L == NULL){
		return ;
	}
	L = (P_Node)malloc(sizeof(Node));
	if(L == NULL){
		printf("初始化失败\n");
		return ;
	}
	L->data = 0;
	L->next = NULL;
	printf("初始化成功!\n"); 
} 
//创建链表
void createTail(P_Node L, int n,int type){
	if(L == NULL){
		return ;
	}
	int i = 0;
	P_Node r,newNode;
	r = L; 
	for(i=0;i<n;i++){
		newNode = (P_Node)malloc(sizeof(Node));
	 	if(newNode == NULL){
	 		printf("创建链表失败!\n");
	 		return ;
	 	}
	 	if(type ==0){
			newNode->data = 2*(i+1)-1;
	 	}else{
 			newNode->data = 2*(i+1);
	 	} 
		newNode->next = r->next;
		r->next = newNode;
		r = newNode;
		
		L->data++; 
	}
	printf("链表创建成功!\n"); 
} 
//合并两个排序链表
P_Node Merge(P_Node p1,P_Node p2){
	if(p1 == NULL)return p2;
	if(p2 == NULL)return p1; 
	P_Node head;
	if(p1->data<p2->data){
		head = p1;
		head->next = Merge(p1->next,p2);
	}else{
		head = p2;
		head->next = Merge(p2->next,p1); 
	}
	return head;
} 

int main(){
	int n = 5;
	int type = 0;
	P_Node L1,L2;
	//L1=1,3,5,7,9
	init(L1);//初始化 
	type = 0;
	createTail(L1,n,type);
	printf("L1:"); 
	print(L1);
	//L2
	init(L2);//初始化 
	n = 4;
	type = 1;
	createTail(L2,n,type);
	printf("L2:"); 
	print(L2);
	
	//合并两个排序链表
	P_Node res = (P_Node)malloc(sizeof(Node));
	res->next = Merge(L1->next,L2->next);
 	printf("\n合并后:");
 	print(res);
	return 0;
} 

18树的子树

#include<stdio.h>
#include<stdlib.h>
#include<stack>
using namespace std;

//定义树结构 
typedef struct Node{
	char data;
	struct Node *Lchild;
	struct Node *Rchild; 
} Node,*P_Node;

//创建树-前序遍历,输入:AB#D##C## 
void create(P_Node &T){
	char data;
	scanf("%c",&data);
	if(data=='#'){
		T = NULL;
		return ; 
	}else{
 		T = (P_Node)malloc(sizeof(Node));
		if(T == NULL){
			printf("创建失败!\n");	
			return ;
		}
		T->data = data;
		create(T->Lchild);
		create(T->Rchild);
	}
} 
//前序遍历
void preOrder(P_Node T){
	if(T == NULL){
		return ;
	}else{
		printf("%c",T->data);
		preOrder(T->Lchild);
		preOrder(T->Rchild);
	}
} 
//中序遍历
void midOrder(P_Node T){
	if(T == NULL){
		return ;
	}else{
		midOrder(T->Lchild);
		printf("%c",T->data);
		midOrder(T->Rchild);
	}
} 
//后序遍历
void afterOrder(P_Node T){
	if(T == NULL){
		return ;
	}else{
		afterOrder(T->Lchild);
		afterOrder(T->Rchild);
		printf("%c",T->data);
	}
} 

//非递归前序遍历 
void pre(P_Node T){
	stack<P_Node> Stack;
	while(T || !Stack.empty()){
		while(T){
			printf("%c",T->data);
			Stack.push(T);
			T = T->Lchild;
		}
		T = Stack.top();
		Stack.pop();
		T = T->Rchild;	
	}	
}
//非递归中序遍历
void mid(P_Node T){
	stack<P_Node>Stack;
	while(T || !Stack.empty()){
		while(T){
			Stack.push(T);
			T = T->Lchild;
		}
		T = Stack.top();
		printf("%c",T->data);
		Stack.pop();
		T = T->Rchild;
		
	}
} 
//非递归后序遍历
void after(P_Node T){
    stack<P_Node> Stack;
    P_Node pCur; //定义指针,指向当前节点  
    P_Node pPre = NULL;//定义指针,指向上一各访问的节点  

    Stack.push(T);
    while(!Stack.empty()){
        pCur = Stack.top();
        //如果当前节点没有左右孩子,或者有左孩子或有孩子,但已经被访问输出,  
        //则直接输出该节点,将其出栈,将其设为上一个访问的节点  
        if((pCur->Lchild==NULL && pCur->Rchild == NULL) ||
        (pPre != NULL && (pCur->Lchild==pPre || pCur->Rchild == pPre))){
            printf("%c",pCur->data);
            Stack.pop();
            pPre = pCur;
        }else{
            //如果不满足上面两种情况,则将其右孩子左孩子依次入栈  
            if(pCur->Rchild != NULL)  
                Stack.push(pCur->Rchild);  
            if(pCur->Lchild != NULL)  
               Stack.push(pCur->Lchild);
        }
    }

} 
//查找子树
bool findSubTree(P_Node TRoot,P_Node T2Root){
	if(T2Root == NULL) return true;
	if(TRoot == NULL) return false;
	if(TRoot->data != T2Root->data)return false; 
	
	return findSubTree(TRoot->Lchild,T2Root->Lchild) && findSubTree(T2Root->Rchild,T2Root->Rchild);
} 

//判断是不是T2是不是T的子树
bool isSubTree(P_Node T,P_Node T2){
	bool isTrue = false;
	if(T !=NULL && T2 != NULL){
		if(T->data == T2->data)
			isTrue = findSubTree(T,T2);
		if(!isTrue)
			isTrue = isSubTree(T->Lchild,T2);
		if(!isTrue)
			isTrue = isSubTree(T->Rchild,T2);
	}
	
	return isTrue;	
} 
int main(){
	P_Node T;
	create(T); //输入AB#D##C## 
	printf("\n------------------------递归遍历-------------------------\n"); 
	printf("前序遍历:");
	preOrder(T);
	printf("\n中序遍历:");
	midOrder(T);
	printf("\n后续遍历:"); 
	afterOrder(T); 
	printf("\n-----------------------非递归遍历-------------------------\n"); 
	printf("\n非递归前序遍历:");
	pre(T);
	printf("\n非递归中序遍历:");
	mid(T);
	printf("\n非递归后序遍历:");
	after(T);
	printf("\n\n--------------判断B#D##是不是AB#D##C##的子树---------------\n"); 
	//fflush(stdin);
	getchar();
	P_Node T2;
	create(T2); //是子树:B#D##;不是子树: BD### 
	preOrder(T2); 
	bool isFound = isSubTree(T,T2);
 	printf("\nT2是否是T的子树:%d\n",isFound);
 	
	printf("\n");	
	return 0;
} 

19二叉树的镜像

 #include<stdio.h>
 #include<stdlib.h>
 #include<stack>
 
using namespace std;

 //定义树的结构
 typedef struct Node {
 	int data;
 	struct Node *Lchild;
 	struct Node *Rchild;
 } Node,*P_Node;
 
 //创建树
 void createTree(P_Node &T){
 	int data;
 	scanf("%d",&data);
 	if(data == 0){
	 	T = NULL;	
	 	return ;
 	}else{
 		T = (P_Node)malloc(sizeof(Node));
 		T->data = data;
 		createTree(T->Lchild);
		createTree(T->Rchild);
 	}
 }
 //前序遍历
 void preOrder(P_Node T){
	if(T == NULL){
		return ;
	}else{
		printf("%3d",T->data);
		preOrder(T->Lchild);
		preOrder(T->Rchild);
	}
 } 
 //非递归前序遍历
 void pre(P_Node T){
 	stack<P_Node>Stack; 
	while(T || !Stack.empty()){
		while(T){
			printf("%3d",T->data);
			Stack.push(T);
			T = T->Lchild;
		}
		T = Stack.top();
		Stack.pop();
		T = T->Rchild;
	}
 } 
 //树的镜像
void treeMirror(P_Node T){
	if(T == NULL)return; //T传入的是NULL 
	if(T->Lchild==NULL && T->Rchild==NULL)return; //T只有一个节点 
	
	P_Node tmp;//交换左右子树 
	tmp = T->Lchild;
	T->Lchild = T->Rchild;
	T->Rchild = tmp;
	treeMirror(T->Lchild);//递归左子树 
	treeMirror(T->Rchild);//递归右子树 
} 
//非递归实现树的镜像 
void treeMirror2(P_Node T){
	stack<P_Node>Stack; 
	while(T || !Stack.empty()){
		while(T){
			if(!(T == NULL) && !(T->Lchild==NULL && T->Rchild==NULL)){
				P_Node tmp;//交换左右子树 
				tmp = T->Lchild;
				T->Lchild = T->Rchild;
				T->Rchild = tmp;
			}
			Stack.push(T);
			T = T->Lchild;
		}
		T = Stack.top();
		Stack.pop();
		T = T->Rchild;
	}
}
	
 int main(){
 	P_Node T;
 	createTree(T); 	
 	printf("\n");
	preOrder(T);
	printf("\n");
	pre(T);
	printf("\n");
	//输出树的镜像
	treeMirror2(T);
	preOrder(T); 
	printf("\n");                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
 }

23从上往下打印二叉树

#include<stdio.h>
#include<queue> //引入队列文件 

using namespace std;
//定义树结构
typedef struct Node{
	char data;
	struct Node *Lchild;
	struct Node *Rchild; 
} Node,*P_Node;

//创建树
void createTree(P_Node &T){
	char data;
	scanf("%c",&data);
	if(data == '#'){
		T = NULL;
		return ; 
	}else{
		T = (P_Node)malloc(sizeof(Node));
		if(T == NULL){
			printf("创建失败!\n");
			return ;
		}
		T->data = data;
		createTree(T->Lchild);
		createTree(T->Rchild); 
	}
} 
//前序遍历
void preOrder(P_Node T){
	if(T == NULL){
		return ;
	}else{
		printf("%c",T->data);
		preOrder(T->Lchild);
		preOrder(T->Rchild); 
	}
} 
//从上到下打印二叉树,基层序遍历 
void TBOrder(P_Node T){
	queue<P_Node>TQueue;  //定义一个队列 
	TQueue.push(T);
	while(!TQueue.empty()){
		T = TQueue.front(); //获取队首 
		TQueue.pop();//出队队首 
		printf("%c",T->data);
		if(T->Lchild)TQueue.push(T->Lchild);//如果有左子树,左子树入栈 
		if(T->Rchild)TQueue.push(T->Rchild); //如果有右子树,右子树入栈 
	}
} 


int main(){
	P_Node T;
	createTree(T);
	preOrder(T);
	printf("\n");
	TBOrder(T);	
	printf("\n"); 
	
	printf("Hello world !\n");
	return 0;
} 

24二叉搜索树的后序遍历序列

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

//验证一个数组是不是一棵树的后序遍历序列 
bool verifyBST(int r[],int length){
	if(r == NULL || length <= 0){
		return false ;
	}	
	int root  = r[length-1]; //取出根节点 
	int i = 0;
	for(i=0;i<length-1;i++){ //计算左子树的长度 ,并判断左子树是否满足二叉搜索树的定义 
		if(r[i]>root)break; 
	}
	int j = i;
	for(j=i;j<length-1;j++){//计算右子树的长度,并判断右子树是否满足二叉搜索树的定义 
		if(r[j]<root)return false;	
	}
	bool left = true;
	if(i>0){ 
		left = verifyBST(r,i); //递归判断左子树部分 
	}
	bool right = true;
	if(i<length-1){
		right = verifyBST(r+i,length-i-1);//递归判断右子树部分(后边多减去1是把根节点位置减掉) 
	}
	
	return (left && right);
} 



int main(){
	int r[]={5,7,6,9,11,10,8};
	bool isTrue = verifyBST(r,7); 
	printf("r[]={5,7,6,9,11,10,8}是否是二叉搜索树的后续遍历序列:%3d\n",isTrue);
	
	printf("二叉搜索树的后序遍历序列\n");
	return 0;
} 

25二叉树中和为某一值得路径

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

using namespace std;
//定义树结构
typedef struct Node{
	int data;
	struct Node *Lchild;
	struct Node *Rchild; 
} Node,*P_Node;

//创建树
void createTree(P_Node &T){
	int data;
	scanf("%d",&data);
	if(data == 0) {
		T = NULL;
	}else{
		T = (P_Node)malloc(sizeof(Node));
		if(T == NULL){
			printf("创建树失败!\n");
			return ;	
		}
		T->data = data;
		createTree(T->Lchild);
		createTree(T->Rchild);
	}	
} 
//递归前序遍历
void preOrder(P_Node T){
	if(T == NULL){
		return ;
	}else{
		printf("%5d",T->data);
		preOrder(T->Lchild);
		preOrder(T->Rchild);
	}
} 
//findPath
void findPath(P_Node T,int sum){
	if(T == NULL){
		return ;
	} 
	stack<P_Node>Stack; 
	vector<int>Vector;
	int currentSum = 0;
	bool isEqual = false;
	bool isLeaf = false;
	while(T || !Stack.empty()){
		while(T){
			Stack.push(T);
			Vector.push_back(T->data);
			
			currentSum = currentSum + T->data; 
			isEqual =  (currentSum == sum);//当前值是否等于查找的和 
			//isLeaf = (T->Lchild == NULL && T->Rchild == NULL);//是否叶子节点 
			vector<int>::iterator it;
			if(isEqual && isLeaf){
				printf("s");
				for(it=Vector.begin();it!=Vector.end();it++)
    				printf("%3d->",*it);
				printf("\n");
			} 
			printf("\n");
			printf("%5d",currentSum);
			T = T->Lchild; 
		} 
		T = Stack.top();
		Vector.pop_back();
		Stack.pop();
		T = T->Rchild;
	}	
}


int main(){
	P_Node T;
	createTree(T);
	printf("\n");
	preOrder(T);
	printf("\n");
	findPath(T,22);
	printf("\n");
	
	printf("二叉树中和为某一值的路径!\n");
	return 0; 
} 

28字符串的排列

#include<stdio.h>
#include<stdlib.h>
//递归执行排列
void doPL(char* str, char* begin){
	if(*begin == '\0'){
		printf("%s\n",str);
	}else{
		for(char* ch=begin;*ch != '\0';++ch){
			char tmp = *ch;
			*ch = *begin;
			*begin = tmp;
			
			doPL(str,begin+1);
			tmp = *ch;
			*ch = *begin;
			*begin = tmp;
		} 
	} 

} 

//字符串的排列
void PL(char* str){
	if(str == NULL)return;
	doPL(str,str);
} 
int main(){
	
	
	char str[] = "abc";	
	printf("字符串%s的排列:\n",str);
	PL(str);
	printf("字符串的排列!\n");
	return 0;
} 

29出现次数超过一半的数

#include<stdio.h>
typedef int ElemType[10];

//打印
void print(ElemType r,int length){
	int i = 0;
	for(i=0;i<length;i++){
		printf("%3d",r[i]);
	}
	printf("\n");
} 
//交换
void swap(ElemType r,int low,int high){
	int tmp = r[low];
	r[low] = r[high];
	r[high] = tmp; 
} 
//获取元素位置
int partition(ElemType	r,int low,int high){
	int privotKey = r[low];
	
	while(low<high){
		while(low<high && r[high]>=privotKey)high--;
		swap(r,low,high);
		while(low<high && r[low]<=privotKey)low++;
		swap(r,low,high);
	}		
	return low;
} 
//检查数组是否合法
bool verifyArray(ElemType r,int length){
	if(r == NULL && length<=0){
		return false;
	}	
	return true;
}
//验证中间数是否超过数组元素的一半 
bool verifyMidNumber(ElemType r,int length,int number){
	int i,times;
	i = times = 0;
	for(i=0;i<length;i++){
		if(r[i]==number)times++;
	}
	if(2*times<=length){
		return false;
	}else{
		return true;
	}	
}
//获取中间元素
void findNumber(ElemType r,int length){
	if(!verifyArray(r,length)){
		return ;
	}
	int low = 0;
	int high = length-1;
	int mid = high>>1; //此处用位移操作代替/2
	
	int index = partition(r,low,high);
	while(index != mid){
		if(index>mid){
			high = index-1;
			index = partition(r,low,high);
		}else{
			low = index+1;
			index = partition(r,low,high);
		}
	}
 	
 	int midNumber = r[mid];
 	if(verifyMidNumber(r,length,midNumber)){
		printf("数组中出现次数超过一半的数是:%d\n",midNumber); 	
 	}else{
 		printf("数组中出现次数超过一半的数是:不存在!\n");
 	}
} 

//获取中间元素2不修改原数组 
void findNumber2(ElemType r,int length){
	if(!verifyArray(r,length))return ;
	int result = r[0];
	int times = 1;
	int i = 0;
	for(i=1;i<length;i++){
		if(times == 0)result  = r[i];
		if(r[i] == result) {
			times++;
		} else{
			times--;
		}
	} 
	if(verifyMidNumber(r,length,result)){
		printf("数组中出现次数超过一半的数是:%d\n",result); 	
 	}else{
 		printf("数组中出现次数超过一半的数是:不存在!\n");
 	}
} 

int main(){
	ElemType r ={6,6,3,2,2,6,6,4,6};
	int length = 9;
	void print(ElemType,int );//打印数组 
	int partition(ElemType,int ,int ); //获取元素的位置
	bool verifyMidNumber(ElemType,int ,int );//验证获取的中间数是否超过数组长度的一半 
	void findNumber(ElemType,int); //获取中间元素的位置
	bool verifyArray(ElemType,int ); //验证数组是否合法 

	
	print(r,length);
	
	//findNumber(r,length);//使用partition 改变原数组 
	findNumber2(r,length);//不改变原来的数组 
	
	print(r,length);
	printf("数组中出现次数超过一半的数\n");
	return 0; 
}

30最小的k个数

#include<stdio.h>
typedef int ElemType[10];

//打印
void print(ElemType r,int length){
	int i =0;
	for(i=0;i<length;i++){
		printf("%3d",r[i]);
	}
	printf("\n");
} 

//交换
void swap(ElemType r,int low,int high){
	int tmp = r[low];
	r[low] = r[high];
	r[high] = tmp; 
} 
//获取元素位置
int partition(ElemType r,int low,int high){
	int privotKey = r[low];
	
	while(low<high){
		while(low<high && r[high]>=privotKey)high--;
		swap(r,low,high);
		while(low<high && r[low]<=privotKey)low++;
		swap(r,low,high);
	}		
	return low;
} 
//查找最小的k个元素
void find(ElemType r,int length, int k){
	int low = 0;
	int high = length - 1;
	int index = partition(r,low,high);
	while(index != k-1){
		if(index>k-1){
			high = index - 1;
			index = partition(r,low,high);
		}else{
			low = index + 1;
			index = partition(r,low,high);
		}
	}
	
	print(r,k); //打印出最小的k个数 
} 

int main(){
	int k = 6;
	int length = 9;
	ElemType r = {9,6,7,8,5,1,2,3,4};
	print(r,length);	//原始数组 
	find(r,length,k);  //打印最小的k个数 
	
	printf("最小的k个数\n");
	return 0;
} 

32连续子数组的最大和

#include<stdio.h>


//连续子数组中的最大和
void subArrayMax(int r[],int length){
	int currSum,maxSum;
	currSum = maxSum = 0;
	for(int i=0;i<length;i++){
		if(currSum<=0){
			currSum = r[i];
		}else{
			currSum += r[i];
		}
		if(currSum>maxSum)maxSum = currSum; 	
	}
	printf("连续子数组中的最大和:%3d\n",maxSum);
} 

int main(){
	int r[] = {1,-2,3,10,-4,7,2,-5};
	subArrayMax(r,8);
	printf("连续子数组中的最大和\n"); 
	return 0;
} 

33二分查找+快排

#include<stdio.h>

typedef int ElemType[9];

//打印
void print(ElemType r,int n){
	int i = 0;
	for(i=0;i<n;i++){
		printf("%3d",r[i]);
	}
	printf("\n");
} 
//交换值
void swap(ElemType r,int low,int high){
	int tmp = r[low];
	r[low] = r[high];
	r[high] = tmp;
} 
//partition
int partition(ElemType r,int low, int high){
	int privotKey = r[low];
	while(low<high){
		while(low<high && r[high]>=privotKey)
			high--;
		swap(r,low,high);
		while(low<high && r[low]<=privotKey)
			low++;
		swap(r,low,high);		
	}
	return low;
} 
//快速排序 
int QSort(ElemType r,int low,int high){
	if(low<high){
		int privot = partition(r,low,high);
		QSort(r,low,privot-1);
		QSort(r,privot+1,high);
	} 
}
//二分查找
void binSearch(ElemType r,int low,int high,int key){
	while(low<=high){
		int mid = (low+high)/2;
		if(r[mid] == key){
			printf("命中!\n");
			return ;
		}else if(r[mid]>key){
			high = mid - 1;
		}else{
			low = mid + 1;
		}
	}
	printf("没有查找到!\n");
} 
int main(){
	ElemType r ={4,3,6,8,9,7,5,1,2};
	int key = 15 ;
	print(r,9);
	QSort(r,0,8);
	print(r,9);	
	printf("查找元素%d的结果:",key);
	binSearch(r,0,8,key);
	
	return 0;
} 

34二进制中1的个数

#include<stdio.h>

//二进中1的个数
void numberOf1(int n){
	int flag = 1;
	int count = 0;
	while(flag){
		if(n & flag){
			count++ ;
		} 
		flag = flag<<1;
	}
	printf("%3d中1的个数%3d\n",n,count);
} 

void numberOf1x(int n){
	int tmp = n;
	int count = 0;
	while(n){
		++count;
		n = (n-1)&n;
	}
	printf("%3d中1的个数%3d\n",tmp,count);
}
int main(){
	int n = 10;
	numberOf1(n);
	numberOf1x(n);
	return 0;
} 

35斐波那契数列

#include<stdio.h>

//常规斐波那契数列-使用递归 
int Feibonacci(unsigned int n){
	if(n <= 0){
		return 0;
	}	
	if(n == 1){
		return 1;	
	} 

	return Feibonacci(n-1)+Feibonacci(n-2) ; 
} 
//使用遍历
void Fei(unsigned int n){
	int res[2] = {0,1}; 
	if(n < 2){
		printf("%3d",res[n]); //特殊情况 
		return ;
	} 	
	long long x = 0;
	long long y = 1;
	long long z = 0;
	unsigned int i = 0;
	for(i=2;i<=n;i++){
		z = x + y;
		x = y;
		y = z;
	}	
	printf("%3lld\n",z);
} 
 
int main(){
	int n = 8;
	//printf("Feibonacci数列第%d个位置上是%d",n,Feibonacci(n));
	Fei(n);
		

	printf("\n斐波那契数列!\n");
	return 0;
} 

36判断链表中是否存在环、环长度

#include<stdio.h>
#include<stdlib.h>
//定义结构体
typedef struct Node{
	int data;
	struct Node *next;
} Node,*P_Node;
//打印
void print(P_Node L){
	P_Node p = L->next;
	while(p != NULL && p != L){
		printf("%3d",p->data);
		p = p->next; 
	}
	printf("\n");
} 
// 初始化
void init(P_Node &L){
	L = (P_Node)malloc(sizeof(Node));
	if(L == NULL){
		printf("初始化失败!\n");
		return ;
	}
	L->data = 0;
	L->next = L; //创建循环链表 
} 
//创建链表
void createTail(P_Node L,int n){
	int i = 0;
	P_Node r = L; 
	for(i=0;i<n;i++){
		P_Node newNode = (P_Node)malloc(sizeof(Node));
		if(newNode == NULL){
			printf("创建链表失败!\n");
			return ;
		}
		newNode->data = i+1;
		newNode->next = r->next;
		r->next = newNode;
		r = newNode; 
		
		L->data++;
	}
} 
//判断链表中是否存在环
void isLoop(P_Node L){
	if(L==NULL && L->next==NULL){//参数过滤 
		return ; 
	} 
	P_Node fast,slow;
	fast = slow = L->next;	
	while(fast->next!=NULL && fast->next->next!=NULL){//循环判断 是否结束循环 
		fast = fast->next->next;
		slow = slow->next;
		if(fast == slow){
			break;
		} 
	} 
	if(fast==slow && slow!=NULL){//跳出循环后 判断是为NULL时跳出的循环还是faste = slow时跳出的循环 
		printf("该链表中存在环\n");
	}else{
		printf("该链表中不存在环\n");
	} 
} 
//判断链表中环的长度
void loopLength(P_Node L){
	if(L==NULL || L->next==NULL){
		return ;
	}
	P_Node fast,slow;
	fast = slow = L->next;
	int length = 0;
	while(fast->next!=NULL && fast->next->next!=NULL){
		fast=fast->next->next;
		slow=slow->next;
		length++;//统计链表中环的长度 
		if(slow==fast){
			break;
		} 
	} 
	if(fast==slow && fast!=NULL){ 
		printf("该链表中存在环,环的长度为(包含头结点):%3d\n",length);
	}else{
		printf("该链表不存在环!\n");
	}
} 
int main(){
	int n = 10;
	P_Node L;
	init(L);
	createTail(L,n);
	print(L);
	isLoop(L);//判断链表中是否存在环 
	loopLength(L); //计算出链表中环的长度 
	
	
	return 0;
} 

37汉诺塔(解析PPT)

#include <stdio.h> //诺塔的算法就3个步骤:第一,把a上的n-1个盘通过c移动到b。第二,把a上的最下面的盘移到c。第三,因为n-1个盘全在b上了,所以把b当做a重复以上步骤就好了。
//第一个塔为初始塔,中间的塔为借用塔,最后一个塔为目标塔  
int i=1;//记录步数  
void move(int n,char from,char to){ //将编号为n的盘子由from移动到to  
	printf("第%d步:将%d号盘子%c---->%c\n",i++,n,from,to);  
}  
void hanoi(int n,char from,char denpend_on,char to){//将n个盘子由初始塔移动到目标塔(利用借用塔)  
    if (n==1){
    	move(1,from,to);//只有一个盘子是直接将初塔上的盘子移动到目的地  
    }else{
		hanoi(n-1,from,to,denpend_on);//先将初始塔的前n-1个盘子借助目的塔移动到借用塔上  
		move(n,from,to);              //将剩下的一个盘子移动到目的塔上  
		hanoi(n-1,denpend_on,from,to);//最后将借用塔上的n-1个盘子移动到目的塔上  
    }  
}  
int  main(){
     printf("请输入盘子的个数:\n");  
     int n;  
     scanf("%d",&n);  
     char x='A',y='B',z='C';  
     printf("盘子移动情况如下:\n");  
     hanoi(n,x,y,z);  
     
     return 0;
} 

38数组原地旋转90°

题目描述:

一个n×n的二维数组,原地顺时针旋转90度,注意是原地哦,就是不能申请其它的空间。

解析: 这个原地顺时针旋转90°可以看成经过两次变换得到,@四年之后是神 所说中沿着副对角线反转然后沿着水平中线反转是一种方法,还有一种是沿着主对角线反转之后沿着垂直反转也是一种方法。 依次类推,可以思考顺时针180°旋转是怎样变换得到的(水平和垂直反转各一次),逆时针90°(主对角线,水平或者副对角线,垂直)。矩阵的变化还蛮多的,小伙伴们可以多思考一下。 代码如下:

#include <iostream>
#include <iomanip>
using namespace std;

#define MIX_ROW 8

void initArr(int arr[][MIX_ROW],int row){
  int i,j,temp=1;
  for(i=0;i<row;i++){
    for(j=0;j<row;j++){
      arr[i][j]=temp++;
    }
  }
}

void printArr(int arr[][MIX_ROW],int row){
  int i,j;
  for(i=0;i<row;i++){
    for(j=0;j<row;j++){
      cout<<setw(2)<<arr[i][j]<<" ";
    }
    cout<<endl;
  }
  cout<<endl;
}
//矩阵顺时针旋转90度,可以认为先沿着主对角线做一个翻转,然后在做一个左右翻转即可
//要原地变换,则交换操作不能申请临时变量,则,可以使用两种方法:
//a=a+b;b=a-b;a=a-b
//a=a^b;b=a^b;a=a^b
void rotateMix(int arr[][MIX_ROW],int row){
  int i,j;
  for(i=0;i<row-1;i++){
    for(j=i+1;j<row;j++){
      arr[i][j]+=arr[j][i];
      arr[j][i]=arr[i][j]-arr[j][i];
      arr[i][j]-=arr[j][i];
    }
  }
  for(i=0;i<row/2;i++){
    for(j=0;j<row;j++){
      arr[j][i]+=arr[j][row-i-1];
      arr[j][row-i-1]=arr[j][i]-arr[j][row-i-1];
      arr[j][i]-=arr[j][row-i-1];
    }
  }
}

int main(int count,char*args[]){
  int arr[MIX_ROW][MIX_ROW];
  initArr(arr,MIX_ROW);
  printArr(arr,MIX_ROW);
  rotateMix(arr,MIX_ROW);
  printArr(arr,MIX_ROW);
  return 0;
}

26复杂链表的复制

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

typedef struct Node{
	int data;
	struct Node *next;
	struct Node *random;
} Node,*P_Node;

//打印
void print(P_Node PHead){
	P_Node p = PHead;
	while(p){
		printf("%3d",p->data);
		p = p->next;
	}
	printf("\n");
} 

//获取链表长度
void length(P_Node PHead){
	P_Node p = PHead;
	int count = 0;
	while(p){
		count++;
		p = p->next;
	}
	printf("此时链表的长度为:%3\n",count);
} 

//创建链表
void create(P_Node &PHead, int length) {
	PHead = (P_Node)malloc(sizeof(Node));
	PHead->data = 1;
	PHead->next = NULL;
	PHead->random = PHead;
	
	P_Node p,newNode;
	p = PHead;
	for(int i=1;i<length;i++){
		newNode = (P_Node)malloc(sizeof(Node));
		newNode->data = i+1;
		newNode->next = p->next;
		newNode->random = newNode;
	 	p->next = newNode;
	 	p = newNode; 
	} 
}
// 复制节点
void copy(P_Node PHead){
		P_Node p,cloneNode;
		p = PHead;
		while(p){
			cloneNode = (P_Node)malloc(sizeof(Node));
			cloneNode->next = p->next;
		 	p->next = cloneNode;
		 	p = cloneNode->next;
		}
} 

//复制节点信息 
void copyInfo(P_Node PHead){
	P_Node p,cloneNode;
	p = PHead;
	while(p){
		cloneNode = p->next;
		cloneNode->data = p->data;
		cloneNode->random = p->random->next;
		p = cloneNode->next;
	}
} 

//拆分节点
P_Node split(P_Node PHead){
	P_Node p,cloneHead,cloneNode;
	p = PHead;
	cloneHead = cloneNode = PHead->next;
	while(cloneNode->next != NULL){
		p->next = cloneNode->next;
		p = cloneNode->next;
		cloneNode->next = p->next;
		cloneNode = p->next; 
	} 
	p->next = NULL;
	
	return cloneHead;
} 

int main(){
	P_Node PHead,cloneHead;
	create(PHead,5); 	//创建链表 
	copy(PHead);					//复制链表结构(插在源节点后) 
	copyInfo(PHead);				// 复制链表信息(data,next,random) 
	cloneHead = split(PHead); 		//拆分链表(奇:原链表;偶:链表副本) 
	
	// 输出原链表
	print(PHead); 
	// 输出clone的链表 
	print(cloneHead); 
	
}

27约瑟夫环

#include<stdio.h>
#include<stdlib.h>
//定义结构体
typedef struct Node{
	int data;
	struct Node *next;
} Node,*P_Node;

//约瑟夫环(n为结点个数,m倍数,k开始位置) 
//思路:创建头结点->创建剩余的节点->移动到k位置上->移动到m-1位置上->出圈->循环 
void josephusRing(int n,int m,int k){ 
	P_Node curr,p,r;//curr为构建循环链表时的当前节点;p为进行判断时的当前节点;r为进行判断时的辅助节点;
	int i;
	//创建头结点即第一个节点 
	p = (P_Node)malloc(sizeof(Node));
	p->data = 1;
	p->next = p;//构建无头结点的循环链表 
	curr = p; //curr为构建链表时的当前节点 
	for(i=1;i<n;i++) {
		P_Node newNode = (P_Node)malloc(sizeof(Node)); 
		newNode->data = i+1;//尾插法 
		newNode->next = curr->next;
		curr->next = newNode;
		curr  = newNode; 
	}
	while(--k)r = p,p = p->next;//将指针p移动到k位置。p为循环链表创建时的第一个节点 
	while(n--){//对n个数依次进行判断 
		for(i=m-1;i--;r=p,p=p->next);//将指针r移动到m-1位置上准备删除。循环结束时指针p指向m位置上 
		r->next = p->next;//删除m位置上的节点
		printf("%d->",p->data);
		free(p);
		p = r->next;//指针p移动到m+1位置上的节点上,开始新一轮的判断 
	} 
} 
 
int main(){
	josephusRing(9,5,1); 
	printf("\n\n哈哈哈!约瑟夫环!\n");
	return 0;
}

点赞