1.设计算法,判断一个带头结点的单链表list是否非递减有序。
自己思路:遍历单链表 ,每遇到一个结点判断,当前结点的值 是否小于 等于后继结点值,若为真则结束循环,该list为非递减序列;否则指针后移,继续判断,直到下一个结点为NULL,结束循环。
简单写下:
L=(list*)malloc(sizeof(list));
list *p=L->next;
if(p==NULL)
return 0;
for(p ;p!=NULL;p=p->next)
if(p->next) return 1;
return 0;
解法:遍历一趟链表,检查每个结点的数据值是否满足此要求。只要发现有不满足的,立即判定链表不是非递减有序的。
bool nondecrease(LinkList& list){
//检查链表是否递减有序,是则函数返回true,否则返回false
LinkList p=list->next; //p为检测指针,定位于首元结点
while(p->next!=NULL) //检测链表
if(p->next <= p->next->data) p=p->link;
else return false; //发现逆序返回false
return true; //检测完未发现逆序返回true
}
2.在非递减有序的带头结点的单链表list中删除值相同的多余结点(值相同的仅保留第一个结点)
思路:令temp=第一个结点值,遍历单链表,从第二个开始,若当前结点的值等于temp,则删除该结点,指针后移;否则更新temp值为当前结点值,指针后移,继续判断,直到p->next==NULL
解析:因为有序列表中值相同的元素排在一块,因此只需检测相邻结点的元素值是否相同,是则删除后一个值相同的结点,否则继续向后检测。
void isSame(LinkList & list){
LinkList p=list->next,q; //检测指针p指向首元结点
while(p!=NULL && p->next!=NULLL) //检测链表
if(p->data==p->next->data){ //若相邻结点值相等
q=p->next;
p->link=q->link; //删除后一个值相同的结点
free(q);
}else
p=p->link;
}
3.在一个带头结点的非 有序的带头结点的单链表list中删除值相同的多余结点(值相同的仅保留第一个结点)
解析:由于链表中结点的元素值是无序排列的,因此针对每个结点*p,需要在其前面链表检查是否有元素值与其相等的结点。如果发现有元素值相同的结点,则删除*p。注意:链表应避免元素的移动
void tidy(LinkList & list){
LinkList pre=list->link,p=pre->link,r;
while(p!=NULL){
for(r=list->link;r!=p;r=r->link)
if(r->data==p->data) break;
if(r!=p){
pre->link=p->link;
free(p);
p=pre->link;
}
}
}
4(★★★).已知list为带头结点的单链表的表头指针,链表中的结点中存储的都是整数,设计算法,求链表中所有整数的平均值。
个人思路:设变量len,sum,每遍历一个结点执行len++,sum=sum+当前结点值,直到结束
float Average(LinkList& list){
LinkLIst p;
int n;
float sum;
for(p=list->link,n=0,sum=0;p!=NULL;p=p->link){
sum=sum+p->data;
n++;
return sum/n;
}
}
5(★★★)用链表保存m个整数,且|data|<n(n为正整数)。设计一个时间复杂度尽可能高效的算法,对于链表中绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点。例如,给定的单链表list如图
个人思路:类似于第3题的思路。遍历单链表,对每个结点*p需在其前面链表检查是否有元素的值的绝对值与其相等的结点,
若发现有元素的值的绝对值相等的结点,则删除*p
解析:本题未限制空间复杂度,故定义一个大小为N(N为链表中所有元素绝对值的最大值)的数组,所有元素的值初始化为0。
在遍历链表的过程中,结点data值的绝对值为下标,查相应数组元素的值是否为1,若此元素已经是1,说明此结点的元素值的绝对值在之前的的链表结点中出现过,将此结点删除,否则,保留该结点并将相应数组元素的值改为1.假设单链表带头结点,
#define N 100
void DeleteABSEqualNode(LinkNode * list){
int a[N],i; //a是[0/1]标志数组
for(i=0;i<N;i++) a[i]=0; //假设所有整数都未选过
if(list->link==NULL){
printf("空,返回!\n");return;}
LinkNode *pre=list,*p=list->link; //p遍历链表,pre是其前驱结点指针
while(p!=NULL){ //遍历单链表
if(a[abs(p->data)]==1){ //等于*p元素绝对值的整数已有
pre->link=p->link; free(p); //从链中摘下*P并释放
p=pre->link; //p指向下一个待访问结点
}
else { //结点*p元素值的绝对值未访问过
a[abs(p->data)]=1; //作访问标志
pre=p;
p=p->link; //p走到下一个结点
}
}
}
6.设有两个按元素值递增次序排列的单链表list1和list2,他们都无头结点。设计算法,将这两个单链表归并为一个按元素非递增次序排列的单链表,并要求利用原来两个链表的结点存放归并后的单链表.(注意重复元素都保留)
个人思路:建立一个新表,分别遍历两个链表,对每个结点进行比较,按插入排序的思想存入新链表
解析:使用两个指针pa和pb分别遍历两个升序链表,并设置一个初始为空的指针list作为结果链表的头指针。算法用一个循环对pa和pb所指结点进行比较,小者链入结果表的前端;当两个链表中有一个遍历完,从另一个链表中剩余部分顺序摘取结点并链入结果链表的前端,由于采用前插法生成结果链表,则结果链表必定降序
void ListMerge(LinkList list1,LinkList list2,LinkList &list){
LinkList pa=list1,pb=list2,q; ///所有链表都没有头结点
list=NULL;
while(pa!=NULL && PB!=NULL){ //两两比较对应结点
if(pa->data < pb->data){
q=pa;
pa=pa->link; //头插结果链表
}
else {
q=pb;
pb=pb->link;
}
if(pa==NULL) pa=pb; //pa指向可能的非空链表
while(pa!=NULL){ //继续处理剩余结点
q=pa; pa=pa->link;
q->link=list; list=q;
}
}