面試遇到的問題,一開始面試官是問我有什麼方案可以實現排行榜,當時給出了兩個方案。後面面試官又在我的其中一種方案上讓我手寫代碼實現排序雙線鏈表的插入,根據score值插入,並且鏈表長度限制在100。
需要考慮的點:1)插入在鏈表表頭的;2)插入到鏈表表尾;3)插入到鏈表中間;4)需要在遍歷整個鏈表的時候統計鏈表的長度;5)如果長度剛好在100而插入剛好在末尾,則此時不需要執行插入操作。完整代碼如下
#include <iostream>
using namespace std;
#define MAX_RANK 100
struct Link {
int score;
int uid;
Link* prev;
Link* next;
Link() {
score = 0;
uid = 0;
prev = NULL;
next = NULL;
}
};
Link* initLink(int n) {
if (n <= 0) {
return NULL;
}
int i = n;
Link *head = new Link;
head->score = i * 2;
Link *node = head;
while (i > 1) {
i--;
node->next = new Link;
node->next->score = i * 2;
node->next->prev = node;
node = node->next;
}
return head;
}
void freeLink(Link *L) {
Link *node = NULL;
while (L) {
node = L->next;
delete L;
L = node;
}
}
Link* insertLinkLimit(Link* L, int score) {
if (L == NULL) {
L = new Link;
L->score = score;
return L;
}
int cnt = 1;
Link *head = L, *tmp = L->next;
if (L->score <= score) {
// 插入鏈表頭
head = new Link;
head->score = score;
head->next = L;
L->prev = head;
cnt++;
}
else {
while (tmp && L->score >= score && tmp->score >= score) {
// 尋找非插入鏈表頭時的插入位置
L = tmp;
tmp = tmp->next;
cnt++;
}
if (tmp == NULL && cnt == MAX_RANK) {
// 剛好是要直接插到第MAX_RANK+1即滿鏈表的尾部,
// 此時不插入,直接返回。
return head;
}
// 其他情況執行插入操作
// 1)在鏈表中間
// 2)在鏈表末尾但是插入後長度沒有超過限制
L->next = new Link;
L->next->score = score;
L->next->next = tmp;
L->next->prev = L;
if (tmp) {
tmp->prev = L->next;
}
L = L->next;
cnt++;
}
// 因爲需要統計長度,所以執行插入操作後還需要遍歷鏈表
while (tmp && cnt < MAX_RANK) {
tmp = tmp->next;
L = L->next;
cnt++;
}
// 如果插入後操作長度限制,則需要刪除最後一個節點。
if (tmp) {
delete tmp;
L->next = NULL;
}
cout << cnt << endl;
return head;
}
void printLink(Link* L) {
while (L) {
cout << L->score << " ";
L = L->next;
}
cout << endl;
}
int main() {
Link *L = initLink(10);
L = insertLinkLimit(L, 111);
printLink(L);
freeLink(L);
return 0;
}
簡單的測試了幾種情況,輸出都是對的。