关于AVL平衡二叉树的c语言实现(函数内部改变指针本身)
2017-05-10 15:14
411 查看
最近在看数据结构就用c语言写了一个AVL树出来,结果可以运行但无结果输出,搜索许多资料后发现是指针传递的问题,这里总结一下。
头文件(修改后的代码)
原先没有输出结果是因为Insert()函数声明与调用指针方法不对,如代码
因为这里的Insert()参数指针是拷贝了一份T的,这里参考一些别人的文章总结一下
指针本身也是一个值,它的值是所指向对象的地址。指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。
而这里如果采用双重星号的方法,此时传递的不再是T指针的值,而是通过&T传递的T指针的地址,此时是参数是引用传递的,引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。因此可以在函数中改变b指针的值,也就是指针指向的对象。
可以看出,对指针取地址,函数定义的时候使用双重星号的作用不仅仅是为指针赋初始值,还可以在函数中改变指针指向哪个对象,而在普通的指针参数传递中,函数只能改变指针指向对象的值,不能改变指针具体指向哪个对象。
这里放一个二级指针使用的讲解:http://blog.csdn.net/bin510729392/article/details/51476327
头文件(修改后的代码)
#ifndef __ggh #define __ggh typedef int ElementType; typedef struct AVLTreeNode *AVLTree,*Position; struct AVLTreeNode{ ElementType Date; AVLTree left; AVLTree right; int Height; }; static int Height(Position P); AVLTree Insert(ElementType *x,AVLTree *T); int Max(int a,int b); #endif源文件
#include "stdafx.h" #include "gg.h" #include "stdlib.h" #include "stdio.h" void PreOrder(AVLTree T); static AVLTree SingleRotateLeft(AVLTree T) { AVLTree T1=T->left; T->left=T1->right; T1->right=T; T->Height=Max(Height(T->left), Height(T->right))+1; T1->Height=Max(Height(T1->left), Height(T1->right))+1; return T1; } static AVLTree SingleRotateRight(AVLTree T) { AVLTree T1=T->right; T->right=T1->left; T1->left=T; T->Height=Max(Height(T->left), Height(T->right))+1; T1->Height=Max(Height(T1->left), Height(T1->right))+1; return T1; } static AVLTree DoubleRotataeleft(AVLTree T) { T->left=SingleRotateRight(T->left); return SingleRotateLeft(T); } static AVLTree DoubleRotataeright(AVLTree T) { T->right=SingleRotateLeft(T->left); return SingleRotateRight(T); } int Height(Position P) { if(P==NULL) return -1; else return (P->Height); } AVLTree Insert(ElementType *x,AVLTree *T) { if(*T== NULL) { *T=(AVLTree)malloc(sizeof(AVLTree)); if(*T==NULL) printf("out of space"); else { (*T)->Date=*x; (*T)->left=(*T)->right=NULL; (*T)->Height=0; } } else { if(*x<(*T)->Date) { (*T)->left=Insert(x,&((*T)->left)); if(Height((*T)->left)-Height((*T)->right)==2) if(*x<((*T)->left->Date)) *T=SingleRotateLeft(*T); else *T=DoubleRotataeleft(*T); } else if(*x>(*T)->Date) { (*T)->right=Insert(x,&((*T)->right)); if(Height((*T)->right)-Height((*T)->left)==2) if(*x>(*T)->left->Date) *T=SingleRotateRight(*T); else *T=DoubleRotataeright(*T); } } return *T; } AVLTree search_Tree(ElementType x,AVLTree T) { while(T) {if(T->Date==x) return T; else if(x<T->Date) search_Tree(x,T->left); else search_Tree(x,T->right); } return T; } void PreOrder(AVLTree T)//qianxubianli { if(T!=NULL) { printf("%d\n",T->Date); PreOrder(T->left); PreOrder(T->right); } } void MiddleOrder(AVLTree T) { if(T!=NULL) { MiddleOrder(T->left); printf("%d\n",T->Date); MiddleOrder(T->right); } } void PostOrder(AVLTree T) { if(T!=NULL) { PostOrder(T->left); PostOrder(T->right); printf("%d\n",T->Date); } } int Max(int a,int b) { if(a>b) return a; else if(b>a) return b; else return a; } int main() { AVLTree T=NULL; AVLTree Q=NULL; int a[]={3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9}; for(int i=0;i<16;i++) Insert(&a[i],&T); PreOrder(T); printf("\n\n"); MiddleOrder(T); system("pause"); }
原先没有输出结果是因为Insert()函数声明与调用指针方法不对,如代码
声明:AVLTree Insert(ElementType x,AVLTree T); 定义: AVLTree Insert(ElementType x,AVLTree T) { if(T== NULL) { T=(AVLTree)malloc(sizeof(AVLTree)); if(T==NULL) printf("out of space"); else { T->Date=x; T->left=T->right=NULL; T->Height=0; } } else { if(x<T->Date) { T->left=Insert(x,T->left); if(Height(T->left)-Height(T->right)==2) if(x<T->left->Date) T=SingleRotateLeft(T); else T=DoubleRotataeleft(T); } else if(x>T->Date) { T->right=Insert(x,T->right); if(Height(T->right)-Height(T->left)==2) if(x>T->left->Date) T=SingleRotateRight(T); else T=DoubleRotataeright(T); } } T->Height=Max(Height(T->left),Height(T->right))+1; return T; }
因为这里的Insert()参数指针是拷贝了一份T的,这里参考一些别人的文章总结一下
指针本身也是一个值,它的值是所指向对象的地址。指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。
而这里如果采用双重星号的方法,此时传递的不再是T指针的值,而是通过&T传递的T指针的地址,此时是参数是引用传递的,引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。因此可以在函数中改变b指针的值,也就是指针指向的对象。
可以看出,对指针取地址,函数定义的时候使用双重星号的作用不仅仅是为指针赋初始值,还可以在函数中改变指针指向哪个对象,而在普通的指针参数传递中,函数只能改变指针指向对象的值,不能改变指针具体指向哪个对象。
这里放一个二级指针使用的讲解:http://blog.csdn.net/bin510729392/article/details/51476327
相关文章推荐
- 函数内部改变指针本身
- what's in string? c语言string类函数实现汇总 都是学习使用指针的好例子啊(算是读书摘抄和笔记吧)
- 关于C语言的函数指针
- C语言关于数组、指针、函数和结构体的其他知识
- c语言进阶之路----关于函数指针的个人心得
- c语言实现函数给主函数中的指针赋值的方法
- 改变 javascript 函数 内部 this 指针 指向 的三种方法
- C语言,仿内核方式实现分级打印 [附:函数指针、回调函数的小示例]
- C语言学习之 通过指向函数的指针 实现函数的调用
- C语言标准库常见函数的内部实现
- 一个关于函数内部指针参数返回的错误调试及分析
- c语言初学-关于指针作为参数并改变它的值的问题
- C语言函数内部改变指针本身
- C语言中关于返回指针的函数和指向函数的指针
- 关于C语言中的函数指针
- 约瑟夫环问题的PHP实现 使用PHP数组内部指针操作函数
- C语言函数内部改变指针本身
- 关于C语言声明、指针、数组、函数、typedef等等的一通“超级扯”
- 关于Java函数传参以及参数在函数内部改变的问题——JAVA值传递与引用最浅显的说明!
- 浅谈在Swift中关于函数指针的实现