数据结构第二章线性表算法设计练习题(C语言)

(1)将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中不允许有重复的数据。

//合并链表La和Lb,合并后的新表使用头指针Lc指向
void MergeList(LinkList &La,LinkList &Lb,LinkList &Lc){
//pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点
pa=La->next; pb=Lb->next; 
Lc=pc=La; //用La的头结点作为Lc的头结点
while(pa && pb){
	//取较小者La中的元素,将pa链接在pc的后面,pa指针后移
	if(pa->data < pb->data){pc->next=pa;pc=pa;pa=pa->next;}
	//取较小者Lb中的元素,将pb链接在pc的后面,pb指针后移
	else if(pa->data > pb->data) {pc->next=pb; pc=pb; pb=pb->next;}
	//相等时取La中的元素,删除Lb中的元素
	else {pc->next=pa;pc=pa;pa=pa->next;q=pb->next;delete pb ;pb =q;}
	}
pc->next=pa?pa:pb; //插入剩余段
delete Lb; //释放Lb的头结点
}

(2)将两个非递减的有序链表合并为一个非递增的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中允许有重复的数据。

//合并链表La和Lb,合并后的新表使用头指针Lc指向
void MergeList(LinkList& La, LinkList& Lb, LinkList& Lc, ) {
//pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点
pa=La->next; pb=Lb->next; 
Lc=pc=La; //用La的头结点作为Lc的头结点 
Lc->next=NULL;
//只要存在一个非空表,用q指向待摘取的元素
while(pa || pb ){
	if(!pa) {q=pb; pb=pb->next;}//La表为空,用q指向pb,pb指针后移
	else if(!pb) {q=pa; pa=pa->next;} //Lb表为空,用q指向pa,pa指针后移
	//取较小者(包括相等)La中的元素,用q指向pa,pa指针后移
	else if(pa->data <= pb->data) {q=pa; pa=pa->next;}
	else {q=pb; pb=pb->next;}//取较小者Lb中的元素,用q指向pb,pb指针后移
	q->next = Lc->next; Lc->next = q; //将q指向的结点插在Lc 表的表头结点之后
	}
delete Lb; //释放Lb的头结点
}

(3)已知两个链表A和B分别表示两个集合,其元素递增排列。请设计算法求出A与B的交集,并存放于A链表中。

//只有同时出现在两集合中的元素才出现在结果表中,合并后的新表使用头指针Lc指向
void Mix(LinkList& La, LinkList& Lb, LinkList& Lc) { 
pa=La->next;pb=Lb->next; //pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点 
Lc=pc=La; //用La的头结点作为Lc的头结点 
//交集并入结果表中
while(pa && pb) { 
	 //从第一个结点开始进行比较,当两个链表La和Lb均为到达表尾结点时,如果两个表中相等的元素时,摘取La表中的元素,删除Lb表中的元素
	if(pa->data == pb->data){ pc->next=pa;pc=pa;pa=pa->next; u=pb;pb=pb->next; delete u;} 
	//如果其中一个表中的元素较小时,删除此表中较小的元素,此表的工作指针后移
	else if(pa->data < pb->data) {u=pa;pa=pa->next; delete u;} 
	//当链表La和Lb有一个到达表尾结点,为空时,依次删除另一个非空表中的所有元素。、
	else {u=pb; pb=pb->next; delete u;} 
	} 
	while(pa) {u=pa; pa=pa->next; delete u;}// 释放结点空间 
	while(pb) {u=pb; pb=pb->next; delete u;}//释放结点空间 
	pc->next=null;//置链表尾标记
	delete Lb; //释放Lb的头结点
}

(4)已知两个链表A和B分别表示两个集合,其元素递增排列。请设计算法求出两个集合A和B 的差集(即仅由在A中出现而不在B中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。

//求两个集合A和B的差集是指在A中删除A和B中共有的元素,即删除链表中的相应结点,所以要保存待删除结点的前驱,使用指针pre指向前驱结点。

//差集的结果存储于单链表 La 中,*n是结果集合中元素个数,调用时为0 
void Difference ( LinkList& La, LinkList& Lb,int *n ) { 
pa=La->next; pb=Lb->next; //pa和pb分别是链表 La 和 Lb 的工作指针,初始化为相应链表的第一个结点 
pre= La ; //pre为 La 中pa所指结点的前驱结点的指针 
//从第一个结点开始进行比较,当两个链表La和Lb均为到达表尾结点时
while (pa&&pb) {
	//如果La表中的元素小于Lb表中的元素,pre置为La表的工作指针pa删除Lb表中的元素
	if (pa->data < pb->data){pre=pa;pa=pa->next;*n++;} //A链表中当前结点指针后移 
	//如果其中一个表中的元素较小时,删除此表中较小的元素,此表的工作指针后移
	else if (pa->data > pb->data)pb=pb->next; //B链表中当前结点指针后移 
	//当链表La和Lb有一个为空时,依次删除另一个非空表中的所有元素 
	else {pre->next=pa->next; LinkList u=pre; pa=pa->next; delete u;} 
	}
}

(5)设计算法将一个带头结点的单链表A分解为两个具有相同结构的链表B、C,其中B表的结点为A表中值小于零的结点,而C表的结点为A表中值大于零的结点(链表A中的元素为非零整数,要求B、C表利用A表的结点)。

void Resolve(Linklist &La, Linklist &Lb){
	//pa和pb分别是链表 La 和 Lb 的工作指针,初始化为相应链表的第一个结点 
	pa=La->next; pb=Lb->next; 
	pre= La ; //pre为 La 中pa所指结点的前驱结点的指针 
    while (pa){
        if (pa->date < 0){
            Linklist p = new Lnode;
            p = pa;               //生成新节点
            pre->next = pa->next; //删除小于0的节点,pre始终为pa的前驱
            pa = pa->next;        //pa后移
            p->next = NULL;       //后插法将元素插入Lb中
            pb->next = p;
            pb = p; //插入
        }
        //大于0
        else {
            pre = pa;
            pa = pa->next; //pre为pa的前驱,pa指针后移动。
        }
    }
}

(6)设计一个算法,通过一趟遍历在单链表中确定值最大的结点。

int GetMax(LinkList L){
	if(L->next == NULL)
		return NULL;
	pmax = L->next;//假定第一个结点中数据具有最大值
	p = L->next->next;
	while (p){//如果下一个结点存在
		if(p->data > pmax->data)
			pmax = p; //如果p的值大于pmax的值,则重新赋值
		p = p->next;//遍历链表
	}
	return pmax->data;
}

(7)设计一个算法,通过遍历一趟,将链表中所有结点的链接方向逆转,仍利用原表的存储空间

void reverse(Linklist& L){
	Linklist q,p=L->next;//p为第一个结点
	L -> next = NULL;//第一个结点后继置空
	while (p){
		q = p->next;//q为p后一结点,和p同样会后移
		p->next = L->next;//p结点后继改为头结点的后继,刚开始为NULL,之后都是有结点的
		L->next = p;//头结点后继变为p结点,最先的是1结点,后面依次为 2 3 4 5
		p = q;//p结点后移
	}
}

(8)设计一个算法,删除递增有序链表中值大于mink且小于maxk的所有元素(mink和maxk是给定的两个参数,其值可以和表中的元素相同,也可以不同 )。

void Delete(Linklist &L, int mink, int maxk){
    Linklist pre = L;
    Linklist p = L->next;
    while (p){
        if (p->date > mink && p->date < maxk){
            pre->next = p->next;
        } //pre为pa前驱,删除不符合的节点
        else{pre = pa;}//如果符合条件,使pre为pa的前驱。
        p = p->next; //指向下一个节点。
    }
}

(9)已知p指向双向循环链表中的一个结点,其结点结构为data、prior、next三个域,写出算法change(p),交换p所指向的结点和它的前缀结点的顺序。

//p是双向循环链表中的一个结点,本算法将p所指结点与其前驱结点交换。
void Change(LinkList p){
	DLnode *q;
	q = p->prior;           // p的前驱q
	q->prior->next = p;     // p的前驱的前驱之后继为p
	p->prior = q->prior;    // p的前驱指向其前驱的前驱。
	q->next = p->next;      // p的前驱的后继为p的后继。 
	p->next->prior = q;     // p的后继的前驱指向原p的前驱
	q->prior = p;           // p与其前驱交换
	p->next = q;            // p的后继指向其原来的前驱
}

(10)已知长度为n的线性表A采用顺序存储结构,请写一时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法删除线性表中所有值为item的数据元素。

//删除值为item的元素(过滤遍历),顺序表的结构类型为SqList
void ListDelete(SqList &L,int item){
    int j = 0;
    for(int i=0; i<L.length;i++){
    	//如果不等于就按顺序排下去,等于就不执行
        if(L.elem[i] != item){
            L.elem[j] = L.elem[i];
            j++;
        }
    }
    L.length = j;
}

你可能感兴趣的:(C语言,数据结构与算法,数据结构,算法,c语言)