好心情说说吧,你身边的情绪管理专家!

好心情说说专题汇总 心情不好怎么办

励志的句子

我们编辑了“数据结构报告”以更好地满足您的需求。俗话说,实践是智慧的源泉,当我们结束一阶段的工作。都需要去书写报告,报告可以提升经济效益。仅供参考,欢迎大家阅读!

数据结构报告(篇1)

一、实验目的:

了解哈夫曼树的思想和相关概念;

1.初始化:能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树。

2.建立编码表:利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。

3.编码:根据编码表对输入的字符串进行编码,并将编码后的字符串输出。

4.译码:利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。

6.计算输入的字符串编码前和编码后的长度,并进行分析,讨论哈夫曼编码的压缩效果。

7.用户界面可以设计成“菜单”方式,能进行交互,根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。

Data:

data:

struct BiNode //二叉树的结点结构 {

};

待编码字符串由键盘输入,输入时用链表存储,链表节点为 struct Node

1.初始化函数(void HuffmanTree::Init(string Input))

2.获得输入字符串的第一个字符,并将其插入到链表尾部,n=1(n记录的是链表

3.1 将当前取出的字符与链表中已经存在的字符逐个比较,如果当前取出

的字符与链表中已经存在的某个字符相同,则链表中该字符的权值加1。

3.2 如果当前取出的字符与链表中已经存在的字符都不相同,则将其加入

到链表尾部,同时n++

4.tSize=n(tSize记录链表中字符总数,即哈夫曼树中叶子节点总数)

源代码:

{

Node *front=new Node; //初始化链表的头结点

throw exception(“堆空间用尽”);

front->next=NULL;

front->character=NULL;

front->count=0;

Node *pfront=front;

Node* New1=new Node;

throw exception(“堆空间用尽”);

New1->character=ch; //将第一个字符插入链表

New1->count=1;

New1->next=pfront->next;

pfront->next=New1;

bool replace=0; //判断在已经写入链表的字符中是否有与当前读出的字符相同的字符 int n=1; //统计链表中字符个数

{

pfront=pfront->next;

if((int)pfront->character == (int)ch) //如果在链表中有与当前字符相同的字符,

{

pfront->count++;

replace=1;

break;

}

}while(pfront->next);

if(!replace) //如果在链表中没找到与当前字符相同的字符,则将该字符作为新成 员插入链表

{

Node* New=new Node;

throw exception(“堆空间用尽”);

New->character=ch;

New->count=1;

New->next=pfront->next;

pfront->next=New;

n++;

}

pfront=front; //重置pfront和replace变量为默认值 replace=0;

}

pfront=front;

{

front=pfront;

pfront=pfront->next;

front;

}

时间复杂度:

2.创建哈夫曼树(void HuffmanTree::CreateCodeTable(Node *p))

算法伪代码:

2. 将存储字符及其权值的链表中的字符逐个写入三叉链表的前tSize个结点

3.1 从存储字符及其权值的链表中取出两个权值最小的结点x,y,记录其

下标x,y。

3.3 将下标为x的结点设置为i结点的左孩子,将下标为y的结点设置为

源代码:

void HuffmanTree::CreateHTree(Node *p,int n)

{

root= new BiNode[2*n-1]; //初始化哈夫曼树

Node *front=p->next;

throw exception(“没有输入字符”);

root[i].data=front->count;

root[i].lchild=-1;

root[i].rchild=-1;

root[i].parent=-1;

front=front->next;

}

front=p;

int New1,New2;

{

SelectMin(New1,New2,0,i); //从0~i中选出两个权值最小的结点

root[New1].parent=root[New2].parent=i; //用两个权值最小的结点生成新结点,

root[i].data=root[New1].data+root[New2].data;//新结点的权值为其孩子的权值的和 root[i].lchild=New1;

root[i].rchild=New2;

root[i].parent=-1;

}

}

时间复杂度:

在选取两个权值最小的结点的函数中要遍历链表,时间复杂度为O(n),故该函数

3.创建编码表(void HuffmanTree::CreateCodeTable(Node *p))

2.4.1 如果当前叶子结点是其双亲的左孩子,则其对应的编码为0,否

2.4.2 child指针指向叶子结点的双亲,parent指针指向child指针的双亲,

源代码:

void HuffmanTree::CreateCodeTable(Node *p)

{

HCodeTable=new HCode[tSize]; //初始化编码表

Node *front=p->next;

{wWw.J458.com

HCodeTable[i].data=front->character; //将第i个字符写入编码表

int parent=root[i].parent; //得到第i个字符对应的叶子节点的双亲

int k=0;

if(tSize==1) //如果文本中只有一种字符,它的编码为0

{

HCodeTable[i].code[k]='0';

k++;

}

while(parent!=-1) //从第i个字符对应的叶子节点开始,寻找它到根结点的路径

{

if(child==root[parent].lchild) //如果当前结点为双亲的左孩子,则编码为0,

HCodeTable[i].code[k]='0';

HCodeTable[i].code[k]='1';

k++;

child=parent;

parent=root[child].parent;

}

HCodeTable[i].code[k]='';

Reverse(HCodeTable[i].code); //将编码逆置

}

{

cout

parent=root[parent].lchild;

parent=root[parent].rchild;

i++;

}

if(tSize==1) //如果编码表只有一个字符,则根结点即为叶子结点 i++;

d.append(1,HCodeTable[parent].data);//将叶子节点对应的字符追加到解码串中 }

cout

}

时间复杂度:

8. 计算哈夫曼编码的压缩比(void HuffmanTree::Calculate(string s1,string s2)) 算法伪代码:

2. 获得编码后的字符串的长度,将其除以8然后向上取整,得到其占用的字

源代码:

void HuffmanTree::Calculate(string s1,string s2)

{

int cal1=s1.length();

int cal2=s2.length();

cal2=ceill((float)cal2/8); //将编码串的比特数转化为字节数 cout

cout

cout

9. 打印哈夫曼树(void HuffmanTree::PrintTree(int TreeNode,int layer) ) 算法伪代码:

3. 根据当前结点所在的层次确定其前面要输出多少空格,先输出空格,在打

源代码:

void HuffmanTree::PrintTree(int TreeNode,int layer)

{

if(TreeNode==-1) //如果待打印结点为空,则返回 return;

{

PrintTree(root[TreeNode].rchild,layer+1); //先打印该结点的右子树,layer记录

cout

cout

PrintTree(root[TreeNode].lchild,layer+1); //打印该结点的左子树

}

}

10. 菜单函数(void HuffmanTree::Menu())

算法伪代码:

1. 逐一读取键盘缓存区中的字符,并将它们逐一追加到记录输入字符串的

3.利用string变量创建哈夫曼树,初始化编码表。

cout

string Input;

char letter;

{

letter=cin.get();

Input.append(1,letter);

}while(letter!=' ');

Input.erase(Input.length()-1,1); //去掉Input末尾的回车符

Init(Input); //根据输入的字符串创建哈夫曼树及其编码表 cout

PrintTree(2*tSize-1-1,1); //打印哈夫曼树

cout

string d1,d2;

cout

cout

cout

Calculate(Input,d1); //计算编码前后的压缩比

1.由于题目要求能输入任意长的字符串,所以本程序采用了string变量来记录输入

2.打印哈夫曼树时采用了递归函数,且采用了凹凸表的形式打印哈夫曼树。

主函数流程图:

经过这次实验,我了解了哈夫曼树的创建过程,了解了一种不等长编码的方法,用设断点调试的方法更加熟练,同时熟悉了STL中string类型的用法,对C++更加熟悉

数据结构报告(篇2)

1.判断链表是否存在环型链表问题:判断一个链表是否存在环,例如下面这个链表就存在一个环:

例如N1->N2->N3->N4->N5->N2就是一个有环的链表,环的开始结点是N5这里有一个比较简单的解法,设置两个指针p1,p2。每次循环p1向前走一步,p2向前走两步。直到p2碰到NULL指针或者两个指针相等结束循环。如果两个指针相等则说明存在环。

{

int data;

link* next;

};

{

link* p1=head, *p2 = head;

if (head ==NULL || head->next ==NULL)

{

return false;

}

do{

p1= p1->next;

p2 = p2->next->next;

} while(p2 && p2->next && p1!=p2);

return false;

}

2,链表反转 单向链表的反转是一个经常被问到的一个面试题,也是一个非常基础的问题。比如一个链表是这样的: 1->2->3->4->5 通过反转后成为5->4->3->2->1。最容易想到的方法遍历一遍链表,利用一个辅助指针,存储遍历过程中当前指针指向的下一个元素,然后将当前节点元素的指针反转后,利用已经存储的指针往后面继续遍历。源代码如下:

struct linka {

int data;

linka* next;

};

return;

linka*pre, *cur, *ne;

pre=head;

cur=head->next;

{

ne = cur->next;

cur->next = pre;

pre = cur;

cur = ne;

}

head->next = NULL;

head = pre;

}

还有一种利用递归的方法。这种方法的基本思想是在反转当前节点之前先调用递归函数反转后续节点。源代码如下。不过这个方法有一个缺点,就是在反转后的最后一个结点会形成一个环,所以必须将函数的返回的节点的next域置为NULL。因为要改变head指针,所以我用了引用。算法的源代码如下:

linka* reverse(linka* p,linka*& head)

{

if(p == NULL || p->next == NULL)

{

head=p;

{

linka* tmp = reverse(p->next,head);

tmp->next = p;

return p;

}

}

3,判断两个数组中是否存在相同的数字 给定两个排好序的数组,怎样高效得判断这两个数组中存在相同的数字?

这个问题首先想到的是一个O(nlogn)的算法。就是任意挑选一个数组,遍历这个数组的所有元素,遍历过程中,在另一个数组中对第一个数组中的每个元素进行binary search。用C++实现代码如下:

bool findcommon(int a[],int size1,int b[],int size2)

{

int i;

for(i=0;i

{

int start=0,end=size2-1,mid;

{

mid=(start+end)/2;

return true;

else if (a[i]

start=mid+1;

}

}

return false;

}

后来发现有一个 O(n)算法,

因为两个数组都是排好序的。所以只要一次遍历就行了。首先设两个下标,分别初始化为两个数组的起始地址,依次向前推进。推进的规则是比较两个数组中的数字,小的那个数组的下标向前推进一步,直到任何一个数组的下标到达数组末尾时,如果这时还没碰到相同的数字,说明数组中没有相同的数字。

bool findcommon2(int a[], int size1, int b[], int size2)

{

int i=0,j=0;

while(ireturn true;j++;if(a[i]i++;}return false;}4,最大子序列 问题:给定一整数序列A1, A2,... An (可能有负数),求A1~An的一个子序列Ai~Aj,使得Ai到Aj的和最大例如:整数序列-2, 11, -4, 13, -5, 2, -5, -3, 12, -9的最大子序列的和为21。对于这个问题,最简单也是最容易想到的那就是穷举所有子序列的方法。利用三重循环,依次求出所有子序列的和然后取最大的那个。当然算法复杂度会达到O(n^3)。显然这种方法不是最优的,下面给出一个算法复杂度为O(n)的线性算法实现,算法的来源于Programming Pearls一书。 在给出线性算法之前,先来看一个对穷举算法进行优化的算法,它的算法复杂度为O(n^2)。其实这个算法只是对对穷举算法稍微做了一些修改:其实子序列的和我们并不需要每次都重新计算一遍。假设Sum(i, j)是A[i] ... A[j]的和,那么Sum(i, j+1) = Sum(i, j) + A[j+1]。利用这一个递推,我们就可以得到下面这个算法:{int i,j,v,max=a[0];for(i=0;i{v=0;for(j=i;j{v=v+a[j];//Sum(i, j+1) = Sum(i, j) + A[j+1]max=v;}}return max;}那怎样才能达到线性复杂度呢?这里运用动态规划的思想。先看一下源代码实现:{int i,max=0,temp_sum=0;for(i=0;i{temp_sum+=a[i];max=temp_sum;temp_sum=0;}return max;}在这一遍扫描数组当中,从左到右记录当前子序列的和temp_sum,若这个和不断增加,那么最大子序列的和max也不断增加(不断更新max)。如果往前扫描中遇到负数,那么当前子序列的和将会减小。此时temp_sum 将会小于max,当然max也就不更新。如果temp_sum降到0时,说明前面已经扫描的那一段就可以抛弃了,这时将temp_sum置为0。然后,temp_sum将从后面开始将这个子段进行分析,若有比当前max大的子段,继续更新max。这样一趟扫描结果也就出来了。5, 找出单向链表的中间结点 这道题和解判断链表是否存在环,我用的是非常类似的方法,只不过结束循环的条件和函数返回值不一样罢了。设置两个指针p1,p2。每次循环p1向前走一步,p2向前走两步。当p2到达链表的末尾时,p1指向的时链表的中间。{link* p1,*p2;p1=p2=head;if(head==NULL || head->next==NULL)return head;do {p1=p1->next;p2=p2->next->next;} while(p2 && p2->next);return p1;}来自:akalius.blog/163319

数据结构报告(篇3)

二.实验目的:

1、使学生熟练掌握哈夫曼树的生成算法。

2、熟练掌握哈夫曼编码的方法。

三.问题描述:

已知n个字符在原文中出现的频率,求它们的哈夫曼编码。

1、读入n个字符,以及字符的权值,试建立一棵Huffman树。

2、根据生成的Huffman树,求每个字符的Huffman编码。并对给定的待编码字符序列进行编码,并输出。

typedef struct{

unsigned int weight;

unsigned int parent,lchild,rchild;

}HTNode,*HuffmanTree; //动态分配数组存储郝夫曼树

typedef char* *HuffmanCode;//动态分配数组存储郝夫曼编码

(2)主要的实现思路:

1.基本上没有什么太大的问题,在调用select这个函数时,想把权值最小的两个结点的序号带回HuffmanCoding,所以把那2个序号设置成了引用。

2.在编程过程中,在什么时候分配内存,什么时候初始化花的时间比较长

3.最后基本上实现后,发现结果仍然存在问题,经过分步调试,发现了特别低级的输入错误。把HT[i].weight=HT[s1].weight+HT[s2].weight;中的s2写成了i

typedef struct{

int parent,lchild,rchild;

}HTNode,*HuffmanTree;

typedef char* *HuffmanCode;

void Select(HuffmanTree &HT,int k,int &s1,int &s2)

{ int i;

i=1;

while(i

s1=i;

{

if(HT[i].parent==0&&HT[i].weight

{

if(HT[i].parent==0&&i!=s1)break;

}

s2=i;

{

if(HT[i].parent==0&&i!=s1&&HT[i].weight

}

void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)

{

int m,c,f,s1,s2,i,start;

char *cd;

if(n

HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); //0号单元未用,预分配m+1个单元

HuffmanTree p=HT+1;

{

p->weight=*w;

p->parent=p->rchild=p->lchild=0;

{

p->weight=p->parent=p->rchild=p->lchild=0;

{

Select(HT,i-1,s1,s2); //选出当前权值最小的

HT[s1].parent=i;

HT[s2].parent=i;

HT[i].lchild=s1;

HT[i].rchild=s2;

HT[i].weight=HT[s1].weight+HT[s2].weight;

HC=(HuffmanCode)malloc((n+1)*sizeof(char*)); //分配n个字符编码的头指针变量

cd=(char*)malloc(n*sizeof(char)); //分配求编码的工作空间

for(i=1;i

for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent) //从叶子到根逆向求编码

{

if(HT[f].lchild==c)cd[--start]='0';

cd[--start]='1';

}

HC[i]=(char*)malloc((n-start)*sizeof(char)); //为第i个字符编码分配空间

strcpy(HC[i],&cd[start]);//从cd复制编码到HC

HuffmanTree HT;

HuffmanCode HC;

cout

cin>>n;

w=(int*)malloc((n+1)*sizeof(int)); //记录权值,号单元未用

ch=(char*)malloc((n+1)*sizeof(char));//记录字符,号单元未用

cout

{

cout

}

数据结构报告(篇4)

一、实验目的及要求

1)掌握栈和队列这两种特殊的线性表,熟悉它们的特性,在实际问题背景下灵活运用它们。

本实验训练的要点是“栈”和“队列”的观点;

二、实验内容

1) 利用栈,实现数制转换。

2) 利用栈,实现任一个表达式中的语法检查(选做)。

3) 编程实现队列在两种存储结构中的基本操作(队列的初始化、判队列空、入队列、出队列);

三、实验流程、操作步骤或核心代码、算法片段

顺序栈:

Status InitStack(SqStack &S)

{

S.base=(ElemType*)malloc(STACK_INIT_SIZE*sizeof(ElemType));

if(!S.base)

return ERROR;

S.top=S.base;

S.stacksize=STACK_INIT_SIZE;

return OK;

}

Status DestoryStack(SqStack &S)

{

free(S.base);

return OK;

}

Status ClearStack(SqStack &S)

{

S.top=S.base;

return OK;

}

Status StackEmpty(SqStack S)

{

if(S.base==S.top)

return OK;

return ERROR;

}

int StackLength(SqStack S)

{

return S.top-S.base;

}

Status GetTop(SqStack S,ElemType &e)

{

if(S.top-S.base>=S.stacksize)

{

S.base=(ElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(ElemType));

if(!S.base) return ERROR;

S.top=S.base+S.stacksize;

S.stacksize+=STACKINCREMENT;

}

*S.top++=e;

return OK;

}

Status Push(SqStack &S,ElemType e)

{

if(S.top-S.base>=S.stacksize)

{

S.base=(ElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(ElemType));

if(!S.base)

return ERROR;

S.top=S.base+S.stacksize;

S.stacksize+=STACKINCREMENT;

}

*S.top++=e;

return OK;

}

Status Pop(SqStack &S,ElemType &e)

{

if(S.top==S.base)

return ERROR;

e=*--S.top;

return OK;

}

Status StackTraverse(SqStack S)

{

ElemType *p;

p=(ElemType *)malloc(sizeof(ElemType));

if(!p) return ERROR;

p=S.top;

while(p!=S.base)//S.top上面一个...

{

p--;

printf("%d ",*p);

}

return OK;

}

Status Compare(SqStack &S)

{

int flag,TURE=OK,FALSE=ERROR;

ElemType e,x;

InitStack(S);

flag=OK;

printf("请输入要进栈或出栈的元素:");

while((x= getchar())!='#'&&flag)

{

switch (x)

{

case '(':

case '[':

case '{':

if(Push(S,x)==OK)

printf("括号匹配成功!\n\n");

break;

case ')':

if(Pop(S,e)==ERROR || e!='(')

{

printf("没有满足条件\n");

flag=FALSE;

}

break;

case ']':

if ( Pop(S,e)==ERROR || e!='[')

flag=FALSE;

break;

case '}':

if ( Pop(S,e)==ERROR || e!='{')

flag=FALSE;

break;

}

}

if (flag && x=='#' && StackEmpty(S))

return OK;

else

return ERROR;

}

链队列:

Status InitQueue(LinkQueue &Q)

{

Q.front =Q.rear=

(QueuePtr)malloc(sizeof(QNode));

if (!Q.front) return ERROR;

Q.front->next = NULL;

return OK;

}

Status DestoryQueue(LinkQueue &Q)

{

while(Q.front)

{

Q.rear=Q.front->next;

free(Q.front);

Q.front=Q.rear;

}

return OK;

}

Status QueueEmpty(LinkQueue &Q)

{

if(Q.front->next==NULL)

return OK;

return ERROR;

}

Status QueueLength(LinkQueue Q)

{

int i=0;

QueuePtr p,q;

p=Q.front;

while(p->next)

{

i++;

p=Q.front;

q=p->next;

p=q;

}

return i;

}

Status GetHead(LinkQueue Q,ElemType &e)

{

QueuePtr p;

p=Q.front->next;

if(!p)

return ERROR;

e=p->data;

return e;

}

Status ClearQueue(LinkQueue &Q)

{

QueuePtr p;

while(Q.front->next )

{

p=Q.front->next;

free(Q.front);

Q.front=p;

}

Q.front->next=NULL;

Q.rear->next=NULL;

return OK;

}

Status EnQueue(LinkQueue &Q,ElemType e)

{

QueuePtr p;

p=(QueuePtr)malloc(sizeof (QNode));

if(!p)

return ERROR;

p->data=e;

p->next=NULL;

Q.rear->next = p;

Q.rear=p; //p->next 为空

return OK;

}

Status DeQueue(LinkQueue &Q,ElemType &e)

数据结构报告(篇5)

1、进一步掌握指针变量的含义及应用。

2、掌握二叉树的结构特征,以及各种存储结构的`特点及使用范围。

3、掌握用指针类型描述、访问和处理二叉树的运算。

题目1:编写一个程序,采用一棵二叉树表示一个家谱关系。要求程序具有如下功能:

(1)用括号表示法输出家谱二叉树,

(2)查找某人的所有儿子,

为了能够用二叉树表示配偶、子女、兄弟三种关系,特采用以下存储关系,则能在二叉树上实现家谱的各项运算。

二叉树型存储结构定义为:

struct SNODE *right; //指向兄弟或子女结点

实验由主函数、家谱建立函数、家谱输出函数、儿子查找函数、祖先查找函数、结点定位函数、选择界面函数七个函数共同组成。其功能描述如下:

void InitialFamily(FNODE *&head) //家谱建立函数

输出形式为:父和母(子1和子妻1(孙1),子2和子妻2(孙2))

void PrintFamily(FNODE *head) //家谱输出函数

(4)儿子查找函数:在家谱中查找到某人所有的子女并输出,同时也能辨别出其是否为家族成员与是否有子女

void FindSon(FNODE *b,char p[]) //儿子查找函数

(5)祖先查找函数:在家谱中查找到某人所有的祖先并输出,同时也能辨别出其是否为家族中成员。

int FindAncestor(FNODE *head,char son[ ]) //祖先查找函数

FNODE *findnode(FNODE *b,char p[]) //结点定位函数

(7)选择界面函数:为便于编写程序,将用户选择部分独立为此函数。

(三)各函数的详细设计:

void InitialFamily(FNODE *&head) //家谱建立函数

1:首先建立当前人的信息,将其左右结点置为空,

2:然后让用户确定其是否有配偶,如果没有配偶,则当前程序结束,

3:如果有则建立其配偶信息,并将配偶结点赋给当前人的左结点;

4:再让用户确定其是否有子女,如果有则递归调用家谱建立函数建立子女结点,并将其赋给配偶结点的下一个右结点。

void PrintFamily(FNODE *head) //家谱输出函数

1:首先判断当前结点是否为空,如果为空则结束程序;

3:然后判断其左结点(配偶结点)是否为空,如不为空则输出“和配偶信息。

4:再判断配偶结点的右结点是否为空,如不为空则递归调用输出其子女信息,最后输出“)”;

FNODE *findnode(FNODE *b,char p[]) //结点定位函数

void FindSon(FNODE *b,char p[]) //儿子查找函数

1:在家谱中定位到要查找的结点,如无则输出“查找不到此人”

2:判断其配偶结点与子女结点是否为空,为空则输出“无子女”

3:不为空则输出其配偶结点的所有右结点(子女结点)。

int FindAncestor(FNODE *head,char son[ ]) //祖先查找函数

1:先在家谱中定位到要查找的结点,如为空输出“不存在此人”,程序结束

4:访问过,再判断是否为查找结点,如是则输出栈中保存的其祖先结点,并滤过其兄弟结点不输出;不是查找结点,则退栈一个元素

5:未访问过,则取当前栈顶元素,置访问标志——1,同时取其右结点

转载请保留原文链接:http://www.j458.com/a/5621039.html,并在标注文章来源。
上一篇 : 卖房子文案干净短句通用46句
下一篇 : 以前羞涩自己说说合集(36句)