题目:假设该链表只给出了头指针L,在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k为正整数)。若查找成功,算法输出该结点data域的值,并返回1;不则只返回0。
输入:带头结点的链表个元素的值,类型为int,以9999结束。
输出:查找倒数的k个结点,输出该元素值。
优化目标:无。
算法思想:定义两个指针p和q,初始时均指向头结点的下一个结点(链表的第一个结点),p指针沿链表移动;当p指针移动到第k个结点时,q指针开始和p指针同步移动,当p指针移动到最后一个结点时,q指针所指示结点为倒数第k个结点。
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
int Search_k(LinkList L,int k){
LNode *p,*q;
p = L->next;
q = L->next;
int count = 0;
while(p!=NULL){
if(countnext;
}
p = p->next;
}
if(countdata;
}
}
//创建链表
void creatList(LinkList &L){
LNode *s,*r;
int x;
printf("请输入链表元素值(以9999结束):");
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
r = L;
scanf("%d",&x);
while(x!=9999){
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
s->next = NULL;
r = s;
scanf("%d",&x);
}
}
//输出链表
void PrintList(LinkList L){
LNode *p = L->next;
printf("链表元素有:");
while(p!=NULL){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main() {
LinkList L;
creatList(L);
PrintList(L);
printf("请输入想要查询倒数的位置:");
int k;
scanf("%d",&k);
int kk = Search_k(L,k);
printf("查找的结点是:%d",kk);
return 0;
}
题目:用单链表保存m个整数,结点的结构为[data][ next],且ldatal<=n(n为正整数)。现要求设计一个时间复杂度尽可能高效的算法,对于链表中data的绝对值相等的结点,仅保留第一次出现的结点而删除其余结点。
输入:带头结点的链表个元素的值,类型为int,以9999结束。
输出:删除绝对值相等的结点之后,输出单链表。
优化目标:无。
算法思想:用空间换时间。使用辅助数组记录链表中已经出现的数值,从而只需对链表进行一趟扫描。
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
void del_absrepeat(LinkList L){
LNode *p = L,*s;
int *q,m,n = 0;
s = L;
while(s->next!=NULL){
n++;
s = s->next;
}
q = (int *)malloc(sizeof(int)*(n+1));
for(int i = 0;inext!=NULL){
if(p->next->data>0){
m = p->next->data;
}
else{
m = -(p->next->data);
}
if(*(q+m) == 0){
*(q+m) = 1;
p = p->next;
}
else{
s = p->next;
p->next = s->next;
free(s);
}
}
free(q);
}
//创建链表
void creatList(LinkList &L){
LNode *s,*r;
int x;
printf("请输入链表元素值(以9999结束):");
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
r = L;
scanf("%d",&x);
while(x!=9999){
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
s->next = NULL;
r = s;
scanf("%d",&x);
}
}
//输出链表
void PrintList(LinkList L){
LNode *p = L->next;
printf("链表元素有:");
while(p!=NULL){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main() {
LinkList L;
creatList(L);
PrintList(L);
del_absrepeat(L);
PrintList(L);
return 0;
}
题目:暗点设计一个算法完成以下功能:判断一个链表是否有环,如果有,找出环的入口并返回,否则返回NULL。
输入:创建带头结点的链表(带环)个元素的值,类型为int,以9999结束。
输出:找到环的入口点,输出入口点的值。
优化目标:无。
算法思想:设置快慢两个指针分别为fast和slow,slow每走一步,fast走两步,所以如果有环,那么fast一定会先进入环,而slow后进入环。当两个指针都进入环后,经过若干次操作后两个指针一定能在环上相遇。这样就可以判断一个链表是否有环。设头结点到环入口的距离为a,环的入口点沿环的方向到相遇点的距离为x,环长尾r入队,相遇时fast绕过了n圈,所以2(a+x)=a+n*r+x,即a=n*r-x,所以从头结点到环入口点的距离等于环长减去环的入口点到相遇点的距离,所以设置两个指针,一个指向L,一个指向相遇点,两个指针同步移动(均一次移动一步),相遇点就是环的入口点。
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
LNode* FindLoopStart(LinkList L){
LNode *fast = L->next,*slow = L->next;
while(slow!=NULL&&fast->next!=NULL){
slow = slow->next;
fast = fast->next->next;
if(slow == fast){
break;
}
}
if(slow == NULL||fast->next == NULL){
return NULL;
}
LNode *p1 = L->next,*p2 = slow;
while(p1!=p2){
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
//创建链表
void creatList(LinkList &L){
LNode *s,*r,*p;
int x;
printf("请输入链表元素值(以9999结束):");
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
r = L;
scanf("%d",&x);
s = (LNode *)malloc(sizeof(LNode));
s->data = 1;
r->next = s;
s->next = NULL;
r = s;
s = (LNode *)malloc(sizeof(LNode));
s->data = 2;
r->next = s;
s->next = NULL;
r = s;
s = (LNode *)malloc(sizeof(LNode));
s->data = 3;
r->next = s;
s->next = NULL;
r = s;
p = s;
while(x!=9999){
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
s->next = NULL;
r = s;
scanf("%d",&x);
}
r->next = p;
}
//输出链表
void PrintList(LinkList L){
LNode *p = L->next;
printf("链表元素有:");
while(p!=NULL){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main() {
LinkList L;
creatList(L);
LNode *p = FindLoopStart(L);
printf("入口结点元素是:%d",p->data);
return 0;
}
题目:设线性表L = (a1a2,a3,...,a(n-2),a(n-1),an)采用带头结点的单链表保存,请设计一个空间复杂度为O(1),且时间上尽可能高效的算法,重新排列L中的各结点,得到线性表L‘ = (a1,a(n),a2,a(n-1),a3,a(n-2))。
输入:带头结点的链表个元素的值,类型为int,以9999结束。
输出:按要求排序好单链表后,输出单链表。
优化目标:无。
算法思想:首先取出表的后半段,利用p和q指针,p移动一步,q移动两步,当q到达表尾时,p正好在链表的中间结点,然后将L的后半段结点原地逆置,从单链表前后两段各取一个结点,按要求重排。
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
void change_List(LinkList &L){
LNode *p,*q,*r,*s;
p = q = L;
while(q->next!=NULL){
p = p->next;
q = q->next;
if(q->next!=NULL){
q = q->next;
}
}
q = p->next;
p->next = NULL;
while(q!=NULL){
r = q->next;
q->next = p->next;
p->next = q;
q = r;
}
s = L->next;
q = p->next;
p->next = NULL;
while(q!=NULL){
r = q->next;
q->next = s->next;
s->next = q;
s = q->next;
q = r;
}
}
//创建链表
void creatList(LinkList &L){
LNode *s,*r;
int x;
printf("请输入链表元素值(以9999结束):");
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
r = L;
scanf("%d",&x);
while(x!=9999){
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
s->next = NULL;
r = s;
scanf("%d",&x);
}
}
//输出链表
void PrintList(LinkList L){
LNode *p = L->next;
printf("链表元素有:");
while(p!=NULL){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main() {
LinkList L;
creatList(L);
PrintList(L);
change_List(L);
PrintList(L);
return 0;
}
今日总结:做了几道单链表的题,还要好好复习之前的内容,今天题总体来说不是很难,后面还要加油多练。