数据结构1
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、((本题15分)试设计一个结点数据类型为整型的带表头结点的有序单
链表,然后设计一个算法,该算法将这个有序单链表划分成两个单链表,使得第一个单链表中包含原单链表中所有数值为奇数的结点,第二个单链表中包含原单链表中所有数值为偶数的结点,且两个单链表中结点的相对排列顺序与原单链表中相同。注意:要求使用原单链表的空间,表头结点可以另辟空间。
[解答]
void split(LinkList &HL, LinkList &L1, LinkList &L2) {
q1=L1= (LinkList) malloc(sizeof(LNode));
q2=L2= (LinkList) malloc(sizeof(LNode));
p=HL->next;
while (p!=NULL) {
if (p->date % 2 != 0) {
q1->next= p; q1=p;}
else
q2->next= p; q2=p;}
p=p->next;
}
q1->next=q2->next=NULL;
free(HL);
}
二、(本题20分)试设计一个递归算法,判断二叉树T是否是满二叉树,假
设T是以二叉链表存储。
typedef struct BiTNode{
TElemType data;
Struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
解答:
满二叉树中任一个结点为根的子树都是满二叉树。
算法:
(1)如果二叉树T是空树,则是满二叉树;
(2)如果二叉树T非空,左右子树都是满二叉树,而且深度一样,则T是满二叉树;(3)如果二叉树T非空,左子树或右子树不是满二叉树,则不是满二叉树;
(4)如果二叉树T非空,左右子树都是满二叉树,但深度不一样,则T不是满二叉树。//该函数判断二叉树T是否是满二叉树
//如果是满二叉树,返回TRUE,Depth返回该树的深度;
//否则返回FALSE,Depth无定义;
Boolean Check( BiTree T, int &Depth)
{ int ldepth, rdepth;
if( T==NULL) { Depth=0; return TRUE; }
if( Check(T->lchild, ldepth)==FALSE ) return FALSE;
if( Check(T->rchild,rdepth)==FALSE) return FALSE;
if( ldepth!=rdepth ) return FALSE;
Depth=ldepth+1; return TRUE;
}
三、(本题15分)试设计算法在O(n)时间内将数组A[1..n]划分为左右两个
部分,使得左边的所有元素为奇数,右边的所有元素均为偶数,要求所使用的辅助存储空间大小为O(1)。
解:该题算法的主要思路如下:
(1)设置两个指针i和j,其中i=1,j=n。
(2)当i i不断自加从左往右找到第一个偶数 j不断自减从右往左找到第一个奇数 A[i]与A[j]交换 (3)算法结束 Adjust(int A[1..n]) { int i=1, j=n; while (i while (A[i] % 2 != 0 && i<=n) i++; while (A[i] % 2 = =0 && j>=1) j--; if (i>n || j<1) break; if (i } } 算法的时间复杂性为O(n),辅助存储空间为O(1)。 应采用堆排序,因为当给定的待排序的记录的关键字基本有序时,快速排序将退化为起泡排序,此情况下的快速排序时间复杂度为O(n2),而堆排序即便在最坏情况下的时间复杂度仍为O(nlogn)。 四、本题10分)给定广义表(a,((),b),(((e)))),完成下列要求: 1)给出广义表的数据结构; 2)画出该广义表的存储结构图; 3)利用取表头和表尾的操作分离出原子e(给出GetHead、GetTail的操作序列)。 [解答] 1)(见课本P109~110) 2) 3)令给定广义表为L,则Gethed(GetHead(GetHead(GetHead(GetTail(Gettail(L))))) 五、(本题15分)试设计一个带头结点的单链表,然后写一个算法将该单链 表逆转,要求利用原表结点空间,不允许申请和使用新的结点空间。 解: 方法一:建立一个新的单链表,其中的结点从原表得来,即每个原表中得到一个结点,就要将此结点插入新链表中。由于要将表逆转,原表的头结点成为新链表的头结点,每次从原表中得到一个结点,此结点插在头结点之后,作为新链表的第一个结点。 void InverLinkedList( LinkList &L){ LNode *p, *s; P=L→next; L→next=NULL; while (p) { s=p; //p为待逆置链表头指针 p=p→next; //从p所指链表中删除第一个结点 s→next=L→next; L→next=s; //将s结点插入到逆置表的表头 } } 方法二:在遍历原表的时候将各结点的指针逆转,从原表的第一个结点开始,表头结点的指针在最后修改成指向原表的最后一个结点。 void InvertLinkedList( LinkList &L) { LNode *p, *q; S=L→next; if (s) { q=NULL; p=s; while (p) { p=p→next;