数据结构期中考试典例分析

 这次考试检验出很多问题,同时也很低分,,,迷茫了半个月,现在爬回来补内容

目录

一、哈夫曼编码手工计算题

二、堆的手工题

三、二叉树遍历算法题

四、双端队列插入删除算法题

五、链表算法题



一、哈夫曼编码手工计算题

1、下面的数据表给出了在一篇有19710个词的英文词文中出现最普遍的确15个词的出现频度

1)假设一个英文字符等价于log26=4.7010bits,那么这些词按bits计的平均长度是多少?

2)假定一篇正文仅由上述数据表中的词组成,那么它们的最佳哈夫曼编码是什么?平均长度是多少?

第一问

想不明白考试怎么没有尝试一下。。

总长度位/ 单词总数目

计算总词数目,简单15个频度和。

(即1192+677+541+……+123)快速得出单词总数目为为5364个单词。

总长度:

1 :541 (单词a)                       2:2508(单词of,to,in,he,is,at,on,be)

3:2073 (单词the,and,for,his,are)                       4:242(单词that)

得到总12744个英文字符。(每个字符的编码位数由题可知是4.701,则。。)

(12744*4.701)/5364   =  11.169

第二问

考试很多时间花在那里,然后还搞乱心态了

其实可以写每一步的编码过程,这样子可以捞过程分的。。。直接写结果可能错了就一点分都没有


二、堆的手工题

 2、请把Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec这个序列调整为最大堆(字典序

没看清楚题,心态混乱,是按照字典序(即a,b,c,d……这样子排序的),所以就整个步骤都做错了。。。。 

 我考试过程中也想到了把序列转化成数字这样子更好理解

Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec

548197621211103

为了避免因为中间错误扣分严重,应写每次调整 

548197621211103

 如上,相当于是数组,然后数组下标为0的是整个堆(树的根节点)(先左子树后右子树),很快就得到了未调整的堆。。

放博客,自学了堆(树形结构应用)_find it %%的博客-CSDN博客

一共调整6次【算法:(currentSize-2)/2  ----->(12-2)/2=5 , 即0-5共6次】 


三、二叉树遍历算法题

3.给出二叉树二叉链表存贮结构的定义;利用叶子节点中的空的右链指针域rchild,编写一个函数将二叉树的所有叶子结点从左向右链接成一个单链表,并返回最左叶子节点的地址

没认真读题,例如(利用叶子节点中的空的右链指针域rchild),这个我在考试中就额外用了其他的next指针,所以就错了

不管是先序,中序后序遍历,叶子节点出现的次序都为从左到右,所以,随便修改下遍历算法即可解决(修改visit就好了)

不懂的可以看这个二叉树基础(遍历)_find it %%的博客-CSDN博客

代码实现1:

//修改先序递归来实现 返回链头为first参数
template <typename T>
void binTree<T>::makeLeftsToLinkListRec(TreeNode<T> * proot , TreeNode<T> * &pre, TreeNode<T> * &first)
{
	
	if (proot != NULL)
	{
		//visit();即为下面那个if语句内容。对叶子节点进行修改指针操作,对非叶子节点不操作
		if (proot ->lchild == NULL && proot ->rchild ==NULL )
			{
				if (pre == NULL) {pre = proot;first = proot;}
				else 
				{
					pre ->rchild = proot ;pre = proot ; 
				}
			}
		makeLeftsToLinkListRec(proot->lchild, pre,first);
		makeLeftsToLinkListRec(proot->rchild, pre,first);
	}
 
};//中后序一样对。大家想想层次遍历可以吗???            我只给3分。

代码实现2:

//修改先序非递归得到实现;
template <typename T>
TreeNode<T> *  binTree<T>::makeLeftsToLinkList()
{
	stack<TreeNode<T> *>  s;
	s.push(p_root);
	TreeNode<T> * now , * first= NULL, *pre = NULL;
	while (!s.empty())
	{
		now = s.top(); s.pop();
		if (now!= NULL) //now为空树,不作任何处理
		{
			//visit(now);
			s.push(now->rchild);
			s.push(now->lchild);
			//visit 操作 即为对叶子节点,创建链表,对非叶子节点,不作任何操作。
			if (now ->lchild == NULL && now ->rchild ==NULL )
			{
				if (pre == NULL) {pre = now;first = now;}
				else 
				{
					pre ->rchild = now ;pre = now ; 
				}
			}
		} 
	}
	return first; 
};

四、双端队列插入删除算法题

若将一个双端队列顺序表示在一维数组V[m]中,两个端点设为end1end2,并组织成一个循环队列。如图3-9所示,试写出双端队列所用指针end1end2的初始化条件及队空与队满条件,并编写基于此结构的相应的插入(EnQueue)新元素和删除(DlQueue)算法。

教材题目(3.26)

看见这题心里想着就是好家伙。。。我看了没几天,看了个标题。。没看内容没理解,常态

双端队列(顺序表)_find it %%的博客-CSDN博客

数据结构与算法分析 3.26 — 双端队列的实现

核心思想

注意循环队列的判空,标识法,0 空,1满; 元素个数判空满;等。

类似教材的使用一个额外元素预留空间法:

判空 end1 == end2

判满 (end2 + 1) mod Maxsize == end1;

删除:del(int  endflag) //哪个端删或2个函数

end1 = (end1 +1) mod m ,

end2 = (end2-1 + m )mod m 注意方向条件

%的作用是防止end2指针跑到end1前面,或者是防止end2,end1指针退后时越界了(不能为-1)

插入:(插入同理,如果不明白可以画图模拟一遍)

end1 = (end1 -1+m )mod m

end2 = (end2+1) mod m

要考虑2端的插入删除(用标记位即可,标记0,1左右插入)


五、链表算法题

5.设头指针为L的带有表头结点的非循环双向链表,其每个结点中除有prior(前驱指针),data(数据)next(后继指针)域外,还有一个访问频度域freq.在链表被启用前,其值均初始化为零,每当在链表中进行一次Locate(L,x)运算时,令元素值为x的结点中freq域的值增1,并使此链表中结点保持按访问频度非增(递减)的顺序排列,同时最近访问的结点排在频度相同的结点前面,以便使频繁访问的结点总是靠近表头.试编写符合上述要求的Locate(L,x)运算的算法,该运算为函数过程,返回找到结点的地址,类型为指针型

读题很重要,我做的时候漏掉了很多关键信息,例如freq是频度排序的基础。总得来说上面的题涉及了删除节点,插入排序(以freq为基础)

首先在双向链表中查找数据值为X的结点,查到后,将结点从链表上摘下,然后再顺着结点的前驱链查找该结点的插入位置。(频度递减,且排在同频度的第一个),并插入到该位置。因为本身就是有序,所以不需要排序

代码

DLinkList Locate(DLinkList &L,ElemType x){
    //本算法先查找数据x,查找成功时结点的访问频度域增1
    //最后将该结点按频度递减插入链表中适当位置(同频度最近访问的在前面)
    
    DNode *p=L->next,*q;  //p为工作指针,q为p的前驱,用于查找插入位置

    while (p&&p->data!=x)
        p = p->>next; //查找值为x的结点

    if(!p){
        printf ("不存在值为x的结点\n");
        exit(0);
    }
    else 
    {
        p->freq++;    //令元素值为x的结点的freq域加1
        p->next->pred=p->pred;
        p->pred->next=p->next;    //将p结点从链表上摘下

        q=p->pred;    //以下查找p结点的插入位置

        while (q!=L && q->freq<=p->freq)
            q=q->pred;

        p->next=q->next;
        q->next->pred=p;  //将p结点插入,一定是排在同频率的第一个
        p->pred=q;
        q->next=p;
    }
    return p ;  //返回值为x的结点的指针
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值