資料結構-連結串列-練習題1
阿新 • • 發佈:2018-11-27
題目
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;
}