题目
2.已知一个带表头结点的单链表,结点结构为data、link,假设该链表只给出了头指针list。
在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k正为整数)。
若查找成功,算法输出该结点的data域的值,并返回1;否则,只返回0.要求:
(1)描述算法的基本设计思想;
(2)描述算法的详细实现步骤;
(3)根据设计思想和实现步骤,采用程序设计语言描述算法,关键之处请给出简要注释。
代码实现
时间复杂度Q(n)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//创建一个整型的链表
typedef struct _NumNode NumNode;
struct _NumNode{
int num;
NumNode * next;
};
//定义一个指针的队列
//数据区域
typedef struct _Node Node;
struct _Node{
NumNode * numNode;
Node * next;
};
//控制区域
typedef struct _Queue Queue;
struct _Queue{
Node * Front;
Node * Rear;
};
//队列实现
//创建一个队列
Queue * creatQueue(){
Node * node=(Node *)malloc(sizeof(Node));
node->next=NULL;
Queue * queue=(Queue *)malloc(sizeof(Queue));
queue->Front=node;
queue->Rear=node;
return queue;
}
//判断是否为空
bool isEmpty(Queue * queue){
return (queue->Front==queue->Rear);
}
//入队
void addQueue(Queue * queue,NumNode * numNode){
//创建一个节点
Node * node=(Node *)malloc(sizeof(Node));
node->numNode=numNode;
node->next=NULL;
//将节点放入队列
queue->Rear->next=node;
//将Rear指向心得节点
queue->Rear=node;
}
//出队
NumNode * DeleteQ(Queue * queue){
if(isEmpty(queue)){
return NULL;
}
else{
Node * node=queue->Front->next;
NumNode * numNode=node->numNode;
queue->Front->next=node->next;
free(node);
return numNode;
}
}
//整形链表实现
//创建
NumNode * creatNumNode(){
NumNode * numNode=(NumNode *)malloc(sizeof(NumNode));
numNode->next=NULL;
return numNode;
}
//添加元素
void addNumNode(NumNode * numNode, int num){
NumNode * node=numNode;
while (node->next!=NULL){node=node->next;}
NumNode * newNode=(NumNode *)malloc(sizeof(NumNode));
newNode->num=num;
newNode->next=NULL;
node->next=newNode;
}
//显示所有元素
void showAllNum(NumNode *numNode){
NumNode * node=numNode->next;
while (node!=NULL){
printf("%d\t",node->num);
node=node->next;
}
}
//查询元素
int findByLastIndex(NumNode * numNode,int lastIndex){
int ct=0;
int flag=0;
NumNode * numNode1=numNode->next;
Queue * queue=creatQueue();
while (numNode1!=NULL){
ct++;
if(ct<=lastIndex){
addQueue(queue,numNode1);
}
else{
flag=1;
addQueue(queue,numNode1);
DeleteQ(queue);
}
numNode1=numNode1->next;
}
if(flag==0){
printf("Not Found\n");
return 0;
}
else{
printf("Found it. %d\n",queue->Front->next->numNode->num);
return 1;
}
}
int main(){
NumNode * numNode=creatNumNode();
for(int i=0;i<10;i++){
addNumNode(numNode,i);
}
showAllNum(numNode);
printf("%d",findByLastIndex(numNode,7));
}
结果
错误示范(不是最快算法);
基本思想
定义链表
为链表添加内容
获取长度
按长度查找
实现步骤
声明一个链表
做插入操作
获取长度实现:
用while(p->next!=NULL){p=p->next;count++}方式获取长度按索引查找指定位置实现:
while(index!=1){p=p->next;index–};- 对索引长度进行封装:
关键步骤:FindNodeByIndex(node,NodeLength(node)-index+1);正向变逆向查找
代码实现
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//定义链表
typedef struct _Node * Node;
struct _Node{
int data;
Node next;
};
//创建一个链表
Node CreatNode(){
Node node=(Node)malloc(sizeof(struct _Node));
node->next=NULL;
return node;
}
//添加一个节点
bool AddNode(Node node,int num){
Node p=node;
while(p->next!=NULL)p=p->next;
Node newN=(Node)malloc(sizeof(struct _Node));
newN->data=num;
newN->next=NULL;
p->next=newN;
return true;
}
//获取链表长度
int NodeLength(Node node){
int length=1;
Node p=node;
while (p->next!=NULL){
p=p->next;
length++;
}
return length;
}
//正向索引查找
int FindNodeByIndex(Node node, int index){
Node p=node;
if(index>NodeLength(node)){
printf("超出当前长度");
return 0;
}
else{
while (index!=1){
p=p->next;
index--;
}
}
printf("Found it :%d\n",p->data);
return 1;
}
//逆向查找
int FindLast(Node node, int last){
if(FindNodeByIndex(node,NodeLength(node)-last+1)==0){
return 0;
}
else{
return 1;
}
}
int main(){
Node node=CreatNode();
for(int i=0;i<10;i++){
AddNode(node,i);
}
FindLast(node,2);
return 0;
}