在各種面試筆試中,單鏈表考察的最多。其中有一道經典的題目「尋找單鏈表倒數第n個元素」。
如果僅僅是這麼問,大多數人想到這不是很簡單麼:先遍歷整個鍊錶獲知整個鍊錶長度l,然後再l-n+1個節點就是所求節點。
但很顯然面試官不滿足於這種問題,而是「一次遍歷尋找單鏈表倒數第n個元素」。這樣的話,該如何找到思路呢?
首先,我們來弄懂幾個細節:
正序和逆序之間的關係:倒數第n個節點的位置=(鍊錶長度-n+1)個節點所在位置。
比如說,鍊錶為:3,4,5,6,7,8,9,我們要查詢倒數5個節點,也就是正數第(7-5+1)=3節點處。到現在問題就變成了,如何合理的設定迴圈次數移動指標。
由於乙個遍歷鍊錶時,我們通過指標只能控制是否到鍊錶末尾(比如p->next!=null),因此我們考慮新增另外乙個指標(p),通過設定這個指標的指向鍊錶的不同位置,來控制另外乙個指標(p1)移動的次數。因此思路為:
建立兩個指標,第乙個先走n步,然後第2個指標也開始走,兩個指標步伐(前進速度)一致。當第乙個結點走到鍊錶末尾時,第二個節點的位置就是我們需要的
倒數第n個節點的值。
**如下:
#include#include#includetypedef int elemtype;
typedef struct nodenode;
//1、初始化鍊錶
void init(node** pnode)
//1、建立鍊錶
node* create(node* phead)
memset(p1, 0, sizeof(node));
printf("輸入節點值(非正數結束):");
scanf_s("%d", &p1->element);//輸入新節點
p1->next = null;
while (p1->element > 0)
else
p2 = p1;//重新讓p2做尾節點
p1 = (node*)malloc(sizeof(node));
if (p1 == null || p2 == null)
memset(p1, 0, sizeof(node));
printf("輸入節點值(非正數結束):");
scanf_s("%d", &p1->element);
p1->next = null;
} printf("鍊錶建立成功\n");
return phead;
}//列印鍊錶
void print(node* phead)
else
printf("\n"); }}
//清空鍊錶
void clear(node* phead)
while (phead->next != null)
printf("鍊錶清空\n");
}//鍊錶長度
int size(node* phead)
printf("鍊錶長度%d\n", size);
return size;
}//鍊錶是否為空
int isempty(node* phead)
printf("鍊錶非空\n");
return 0;
}//獲取指定位置的元素
elemtype get(node* phead, int pos)
if (phead == null)
while (phead != null)
phead = phead->next;
} if (i < pos)
return phead->element;
}elemtype *getaddr(node* phead, elemtype x)
if (x < 0)
while ((phead->element != x) && (phead->next != null))
if ((phead->element != x) && phead != null)
if (phead->element == x)
return &(phead->element);
}//修改指定位置的元素
int modify(node* pnode, int pos, elemtype x)
if (pos < 1)
while (phead != null)
phead = phead->next;
} if (i < pos)
pnode = phead;
pnode->element = x;
printf("modifyelem函式執行,修改%d出值為%d\n",pos,x);
return 1;
}//插入頭節點
int inserthead(node** pnode, elemtype ele)
//插入尾節點
int insertlast(node** pnode, elemtype ele)
phead->next = pinsert;
*pnode = ptmp;
printf("向表尾插入元素:%d\n",ele);
return 1;
}//在指定位置插入元素
int insertmid(node** pnode, int pos, elemtype ele)
if (pos < 1)
while (phead != null)
phead = phead->next;
} if (i < pos)
nhead = phead->next;//儲存後乙個節點
pinsert->next = phead->next;
phead->next = pinsert;
printf("插入中間節點\n");
return 1;
}//刪除指定位置元素
int deletemidele(node** pnode, int pos)
while (phead != null)
phead = phead->next;
} de = phead->next;
phead->next=de->next;
printf("刪除元素成功\n");
return 1;
}//刪除第乙個節點
int delhead(node** pnode)
if (phead->next == null)
phead = phead->next;//設定原先頭節點的下乙個節點為頭節點
*pnode = phead;
printf("刪除頭節點成功\n");
return 1;
}//刪除尾節點
int dellast(node** pnode)
while (phead->next!= null)
printf("刪除尾節點\n");
free(phead);
predel->next = null;
return 1;
}//逆序鍊錶
void reverse(node** pnode)
current = *pnode;//a1
while (current->next!=null)
printf("逆序鍊錶\n");}/*
*判斷鍊錶中是否有環,同時設定兩個指標,每個指標步長不一樣,若有環則一定相遇
*/int hasloop(node* pnode)}}
} printf("hasloop函式執行,不存在環\n");
return 0;
}int hasloop2(node* pnode)
else
}s2 = s2->next;
} s1 = s1->next; }
printf("hasloop2函式執行,不存在環\n");
return 0;
}//一次遍歷查詢倒數第n個元素
int getnodefromback(node* phead, int n, elemtype *e)
if (p->next == null&&i < n - 1)
node* p2 = phead;
while (p != null)
*e = p2->element;
printf("倒數第%d個元素是:%d\n", n, *e);
return 1;
}void main()
經典面試題 尋找單鏈表倒數第n個節點 C C
面試中經常出現的程式設計題之一。最直接的辦法是先遍歷一遍單鏈表,記下鍊錶的節點數,然後再次遍歷,直到到達節點數減去n的節點,返回結果。實際情況中若鍊錶數目很多而n相對不大,這種方法需要大約兩次遍歷。更簡單的實現方法是採用雙指標。乙個指標先從煉表頭開始步進n步,然後另乙個指標從頭開始,兩個指標一同步進...
刪除單鏈表倒數第n個節點
如何刪除單鏈表中的倒數第n個節點?先遍歷一遍單鏈表,計算出單鏈表的長度,然後,從單鏈表頭部刪除指定的節點。description 刪除單鏈表倒數第n個節點,常規解法.param head param n return listnode public static listnode removenth...
尋找單鏈表中倒數第k個結點
題目描述 輸入乙個鍊錶,輸出該鍊錶中倒數第k個結點。為了符合大多數人的習慣,本題從1開始計數,即鍊錶的尾結點是倒數第1個結點。例如乙個鍊錶有6個結點,從頭結點開始它們的值依次是1,2,3,4,5,6.這個鍊錶的倒數第3個結點是值為4的結點。思路分析 為了得到倒數第k個結點,很自然的想法是先走到鍊錶的...