求教。。。为什么传个参指针指向的内容就变了。。

Goclis 2012-12-31 07:28:41
传参前的 root


传参后的 root


函数还没操作为什么root的内容就变了。。

求教~ 谢谢。。

代码如下:

//Ex3.cpp

#include"HuffmanTree.h"
#include<string>
#include <iostream>
#include<stdlib.h>
#include<cmath>
using namespace std;

int main()
{
HuffmanTree HT;
string test="abbcccdddd";
HT.encodeoutput(test);
HT.decodeoutput();
system("pause");
return 0;
}


//HuffmanTree.h

#include<iostream>
#include<string>
#include"MinHeap.h"

struct HuffmanNode
{
float data;
int mark;
HuffmanNode* leftChild,* rightChild,* parent;
HuffmanNode():leftChild(NULL),rightChild(NULL),parent(NULL),mark(-1){}

HuffmanNode(float elem,HuffmanNode* left=NULL,HuffmanNode* right=NULL,HuffmanNode* pr=NULL,int i=-1)
: data(elem),leftChild(left),rightChild(right),parent(pr),mark(i){}

bool operator<=(HuffmanNode& R){return data<=R.data;}
bool operator>(HuffmanNode& R){return data>R.data;}
};

struct CharNode
{
char letter;
int counter;
string code;
CharNode():letter('\0'),counter(0),code(""){}
CharNode(char c,int i,string s):letter(c),counter(i),code(s){}
};


class HuffmanTree
{
public:
HuffmanTree(int n=32);
~HuffmanTree(){deleteTree(root);delete []T;hp.~MinHeap();}
void encodeoutput(string s);
void decodeoutput();
protected:
int len;
CharNode* T;
string codestr;
MinHeap<HuffmanNode> hp;
HuffmanNode* root;
void PlantTree( float w[],int n);
void decoding(string s,HuffmanNode* h,int& x);
void encoding(string s,HuffmanNode* h);
void deleteTree(HuffmanNode* t);
void mergeTree(HuffmanNode& ht1,HuffmanNode& ht2,HuffmanNode* &parent);
};



//HuffmanTree.cpp

#include"HuffmanTree.h"

HuffmanTree::HuffmanTree(int n)
{
T=new CharNode[n];
for(int i=0;i<n;i++)
{
CharNode* temp = T;
temp=new CharNode();
temp++;
}
len=0;
}
void HuffmanTree::PlantTree( float w[],int n)
{
HuffmanNode* parent,first,second,work;
for(int i=0;i<n;i++)
{
work.data=w[i];
work.mark=i;
work.leftChild=NULL;
work.rightChild=NULL;
work.parent=NULL;
hp.Insert(work);
}
for(int i=0;i<n-1;i++)
{
hp.RemoveMin(first);
hp.RemoveMin(second);
mergeTree(first,second,parent);
hp.Insert(*parent);
}
root=parent;
}

void HuffmanTree::mergeTree(HuffmanNode& ht1,HuffmanNode& ht2,HuffmanNode* &parent)
{
parent=new HuffmanNode;
parent->mark=-1;
parent->leftChild=&ht1;
parent->rightChild=&ht2;
parent->data=ht1.data+ht2.data;
ht1.parent=ht2.parent=parent;
}


void HuffmanTree::deleteTree(HuffmanNode* t)
{
if(t!=NULL)
{
deleteTree(t->leftChild);
deleteTree(t->rightChild);
delete t;
}
}


void HuffmanTree::encodeoutput(string s)
{
len=s.length();
if(len==0)
{
cerr<<"Entering error!"<<endl;
exit(1);
}
static int point=0;
for(int i=0;i<len;i++)
{
bool alter=0;
for(int j=0;j<point;j++)
{
CharNode* n=T+j;
if(n->letter==s[i])
{
(n->counter)++;
alter=1;
break;
}
}
if(!alter)
{
CharNode* m=T+point;
m->letter=s[i];
(m->counter)++;
point++;
}
}
float* w=new float[point];
for(int k=0;k<point;k++)
{
CharNode* l=T+k;
w[k]=l->counter;
}
PlantTree(w,point);
encoding(codestr,root);
cout<<"\n\nEncoded output:\n";
cout<<codestr<<endl;
}

void HuffmanTree::decodeoutput()
{
if(len==0)
{
cerr<<"Entering error!"<<endl;
exit(1);
}
cout<<"\n\nDecoded output:\n";
static int position=0;
for(int i=0;i<len;i++)
{
decoding(codestr,root,position);
}
cout<<endl;
}

void HuffmanTree::decoding(string s,HuffmanNode* h,int& x)
{
if((s[x]=='0')&&(h->leftChild!=NULL))
{
x++;
decoding(s,h->leftChild,x);
}
if((s[x]=='1')&&(h->rightChild!=NULL))
{
x++;
decoding(s,h->rightChild,x);
}
if((h->leftChild==NULL)&&(h->rightChild==NULL))
{
int m=h->mark;
CharNode* Temp=(T+m);
char y=Temp->letter;
cout<<y;
return;
}
}

void HuffmanTree::encoding(string s,HuffmanNode* h)
{
if (h != NULL)
{
if (h->leftChild != NULL)
{
encoding( s+"0", h->leftChild);
encoding( s+"0",h->rightChild);
}
else
{
int m=h->mark;
CharNode* Temp=(T+m);
Temp->code=s;
}
}

}


//MinHeap.h

#include<iostream>
using namespace std;

#ifndef MINHEAP_H
#define MINHEAP_H
static const int DefaultSize=64;
template<class E>
class MinHeap
{
public:
MinHeap(int sz=DefaultSize);
MinHeap(E arr[],int n);
~MinHeap(){delete []heap;}
bool Insert(const E& x);
bool RemoveMin(E& x);
bool IsEmpty()const
{
return (currentSize == maxHeapSize)?true:false;
}
void MakeEmpty(){currentSize=0;}
private:
E* heap;
int currentSize;
int maxHeapSize;
void siftDown(int start,int m);
void siftUp(int start);
};

template<class E>
MinHeap<E>::MinHeap(int sz)
{
maxHeapSize=(DefaultSize<sz)?sz:DefaultSize;
heap=new E[maxHeapSize];
if(heap==NULL)
{
cerr<<"堆存储分配失败!"<<endl;
exit(1);
}
currentSize=0;
}


template<class E>
MinHeap<E>::MinHeap(E arr[],int n)
{
maxHeapSize=(DefaultSize<n)?n:DefaultSize;
heap=new E[maxHeapSize];
if(heap==NULL)
{
cerr<<"堆存储分配失败!"<<endl;
exit(1);
}
for(int i=0;i<n;i++)
heap[i]=arr[i];

currentSize=n;
int currentPos=(currentSize-2)/2;
while(currentPos>=0)
{
siftDown(currentPos,currentSize-1);
currentPos--;
}
}

template<class E>
void MinHeap<E>::siftDown(int start,int m)
{
int i=start,j=2*i+1;
E temp=heap[i];
while(j<=m)
{
if(j<m && heap[j]>heap[j+1])
j++;

if(temp<=heap[j])
break;
else
{
heap[i]=heap[j];
i=j;
j=2*j+1;
}
}
heap[i]=temp;
}

template<class E>
void MinHeap<E>::siftUp(int start)
{
int j=start,i=(j-1)/2;
E temp=heap[j];
while(j>0)
{
if(heap[i]<=temp)
break;
else
{
heap[j]=heap[i];
j=i;
i=(i-1)/2;
}
}
heap[j]=temp;
}

template<class E>
bool MinHeap<E>::Insert(const E& x)
{
if(currentSize==maxHeapSize)
{
cerr<<"Heap Full"<<endl;
return false;
}

heap[currentSize]=x;
siftUp(currentSize);
currentSize++;
return true;
}

template<class E>
bool MinHeap<E>::RemoveMin(E& x)
{
if(!currentSize)
{
cout<<"Heap empty."<<endl;
return false;
}

x=heap[0];
heap[0]=heap[currentSize-1];
currentSize--;
siftDown(0,currentSize-1);
return true;
}

#endif
...全文
487 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Goclis 2013-01-01
  • 打赏
  • 举报
回复
引用 2 楼 ZLhy_ 的回复:
看到你的这段代码就一眼看出来了,这是出自<数据结构殷人昆C++版>的,这个问题我之前也遇到过,很郁闷,但是后来才发现错误。 先来看你的这段代码 void HuffmanTree::PlantTree( float w[],int n) { HuffmanNode* parent,first,second,work; for(int i=0;i<n……
嗯 确实是这样~ 我想多问一下 为什么这样会影响传参时指针所指向的内容啊。。 指针在作为参数传入的时候不应该会影响它的内容啊。 这也是我比较困惑的地方 希望能解答下~ 谢谢
疯狂的红豆 2013-01-01
  • 打赏
  • 举报
回复
哈哈 看来我当初纠结这个问题的时候还是很值得的,记得当时和老师还讨论了一番函数传参问题呢,现在能帮到你真的很高兴啊。不过你问题都解决了怎么不给我分呢 能追加更好哈
Goclis 2013-01-01
  • 打赏
  • 举报
回复
引用 8 楼 ZLhy_ 的回复:
在贴这张图之前你的代码是运行不出来的吧,因为树的结构是不正确的,所以父结点与左右孩子结点之间的联系也是不正确的,你可以现在把能正确输出的程序单步调试一下,也会能解决你的问题呢,还有这个我真的为你解答不了了,我也水平有限
代码改过来后就没这问题了 所以我好纳闷~~ 不过还是谢谢你啊~~
疯狂的红豆 2013-01-01
  • 打赏
  • 举报
回复
在贴这张图之前你的代码是运行不出来的吧,因为树的结构是不正确的,所以父结点与左右孩子结点之间的联系也是不正确的,你可以现在把能正确输出的程序单步调试一下,也会能解决你的问题呢,还有这个我真的为你解答不了了,我也水平有限
Goclis 2013-01-01
  • 打赏
  • 举报
回复
引用 6 楼 ZLhy_ 的回复:
呃,指针作为参数在函数中传递是不会改变其值本身的,当然可能会改变其所指向的内容的值。你图中的两个root的值是一样的吧,难道是我看错了?可能会是程序中其他的地方导致的吧,这个我也不是很清楚了,当时没遇到这个情况
root、left、right指向的地方都没变。。。 但是left指向的内容变了 就是第二张图中变红的地方
疯狂的红豆 2013-01-01
  • 打赏
  • 举报
回复
呃,指针作为参数在函数中传递是不会改变其值本身的,当然可能会改变其所指向的内容的值。你图中的两个root的值是一样的吧,难道是我看错了?可能会是程序中其他的地方导致的吧,这个我也不是很清楚了,当时没遇到这个情况
Goclis 2013-01-01
  • 打赏
  • 举报
回复
引用 4 楼 ZLhy_ 的回复:
引用 3 楼 y15851837883 的回复:引用 2 楼 ZLhy_ 的回复:看到你的这段代码就一眼看出来了,这是出自<数据结构殷人昆C++版>的,这个问题我之前也遇到过,很郁闷,但是后来才发现错误。 先来看你的这段代码 void HuffmanTree::PlantTree( float w[],int n) { HuffmanNode* paren……
那个。。我可能没问清楚 我指的不是mergeTree那个函数 你看我贴的那两张图 我主要是想问问 那个root指针在传递给encoding函数前后为什么发生了改变。。 麻烦你了~
疯狂的红豆 2013-01-01
  • 打赏
  • 举报
回复
引用 3 楼 y15851837883 的回复:
引用 2 楼 ZLhy_ 的回复:看到你的这段代码就一眼看出来了,这是出自<数据结构殷人昆C++版>的,这个问题我之前也遇到过,很郁闷,但是后来才发现错误。 先来看你的这段代码 void HuffmanTree::PlantTree( float w[],int n) { HuffmanNode* parent,first,second,work; ……
睡前回复你一下吧,这个问题中传递的是指针没错,但是你在参数中是对指针的内容做修改呢?还是最指针本身做修改呢?如果是对指针所指向的内容修改的话那这题目就没问题了,但是这恰恰不是的,因为你这是在建立一个树的结构,需要用到的是指针的值本身。想想看,一个当前结点指针nodeptr怎么和其左右孩子结点建立关系了?只能用指针的引用了,就是把(nodepte->leftChild)的他引用传递给函数,否则就是错误的。 我觉得我的博客中的那片内存管理的总结说的挺清楚吧,这个我可能说的不是很清楚,这个要搞清楚内存管理的指针与引用的区别。
疯狂的红豆 2012-12-31
  • 打赏
  • 举报
回复
看到你的这段代码就一眼看出来了,这是出自<数据结构殷人昆C++版>的,这个问题我之前也遇到过,很郁闷,但是后来才发现错误。 先来看你的这段代码 void HuffmanTree::PlantTree( float w[],int n) { HuffmanNode* parent,first,second,work; for(int i=0;i<n;i++) { work.data=w[i]; work.mark=i; work.leftChild=NULL; work.rightChild=NULL; work.parent=NULL; hp.Insert(work); } for(int i=0;i<n-1;i++) { hp.RemoveMin(first); hp.RemoveMin(second); mergeTree(first,second,parent); hp.Insert(*parent); } root=parent; } HuffmanNode* parent,first,second,work;这句中的first与second是固定地址的变量,但是你却在这个函数中mergeTree(first,second,parent);中使用了他们两个作为形参,现在来看你的mmergeTree(first,second,parent);函数: void HuffmanTree::mergeTree(HuffmanNode& ht1,HuffmanNode& ht2,HuffmanNode* &parent) { parent=new HuffmanNode; parent->mark=-1; parent->leftChild=&ht1; parent->rightChild=&ht2; parent->data=ht1.data+ht2.data; ht1.parent=ht2.parent=parent; } 在这个函数中的两个引用型变量ht1与ht2其实是和first与second共享内存的,这样子看你就把first与second的地址赋给了*parent,而你的parent是一个new的返回值,所以你的整个哈夫曼树结构是不能正确构建的。 要改的地方就是 void HuffmanTree::mergeTree(HuffmanNode ht1,HuffmanNode ht2,HuffmanNode* &parent) {//将函数参数中的引用去掉,采用值传递 parent=new HuffmanNode; parent->mark=-1; parent->leftChild=new HuffmanNode(ht1);//深复制一个结点 parent->rightChild=new HuffmanNode(ht2); parent->data=ht1.data+ht2.data; 因为结点是new来的了,所以后一句也要改,因为没有空间存储new出的结点所以只能通过parent指向左右孩子再获取该孩子的父结点指针域了 parent->leftChild->parent=parent; parent->rightChild->parent=parent; } 我的一篇博客后面有详细的说明为什么要这么做,是关于内存管理的:http://blog.csdn.net/zlhy_/article/details/8219652 如果改对了 希望多给分哈

64,647

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧