c語言實現單鏈表面試題

2021-08-02 23:56:00 字數 4210 閱讀 9242

首先實現乙個無頭單鏈表

#include

#include

#include

typedef int datatype;

typedef struct listnode

listnode;

//列印

void printlist(listnode* plist)

printf("null");

printf("\n");

}//尾插

void pushback(listnode** pplist, datatype x)

//只有乙個節點

else

if ((*pplist)->next ==

null)

//多個節點

else

node->next = (listnode*)malloc(sizeof(listnode));

node->next->

data

= x;

node->next->next =

null;

}}//尾刪

void popback(listnode** pplist)

else

free(node);

node =

null;

}}//頭插

void pushfront(listnode** pplist, datatype x)

else

}//頭刪

void popfront(listnode** pplist)

else

}//查詢

listnode* find(listnode* plist, datatype x)

plist = plist->next;

}return

null;

}//在pos的前面插入乙個節點

void insert(listnode** pplist, listnode* pos, datatype x)

else

tmp =(listnode*) malloc(sizeof(listnode));

tmp->

data

= x;

head->next = tmp;

tmp->next = pos;

}}//刪除乙個節點

void erase(listnode** pplist, listnode* pos)

else

tmp->next = pos->next;

free(pos);

pos =

null;

}}

1.比較順序表和煉表的優缺點,說說它們分別在什麼場景下使用?

空間上的比較(space)

空間的開闢:

順序表的實現一般是實現連續開闢一段空間(或根據需求動態連續開闢空間),然後在進行資料的增刪查改(靜態順序表),所以順序表一般是固定空間大小的;

單鏈表則是一次只開闢乙個結點的空間,用來儲存當前要儲存的資料及指向下乙個結點或null的指標,所以單鏈表的空間大小是動態變化的。

空間的使用:

當我們不知道要儲存多少資料時,用順序表來開闢的空間如果太大,就會造成一定程度上的浪費。

用單鏈表實現時,因為是每需要儲存乙個資料時,才開闢乙個空間,雖然有非資料項的指標佔空間,但相比順序表來說,浪費不是那麼明顯。(因為鍊錶每次都是開闢的位置都是隨機的,那麼可能會把這塊空間搞得七零八碎,出現很多小的一般使用不到的碎片空間)

對cpu快取記憶體的影響:

順序表的空間一般是連續開闢的,而且一次會開闢儲存多個元素的空間,所以在使用順序表時,可以一次把多個資料寫入快取記憶體,再寫入主存,順序表的cpu快取記憶體效率更高,且cpu流水線也不會總是被打斷;

單鏈表是每需要儲存乙個資料才開闢一次空間,所以每個資料儲存時都要單獨的寫入快取記憶體區,再寫入主存,這樣就造成了,單鏈表cpu快取記憶體效率低,且cpu流水線會經常被打斷。

時間上的比較(time)

查詢隨機元素的時間複雜度:

順序表訪問隨機元素的時間複雜度是o(1),而單鏈表訪問隨機元素的時間複雜度是o(n)。

隨機位置插入、刪除元素的時間複雜度:

順序表在插入隨機位置插入、刪除元素的平均時間複雜度是o(n),

單鏈表在插入隨機位置插入、刪除元素的時間複雜度是o(1)。

應用場景:

根據時間複雜度比較:

在查詢操作使用的比較頻繁時,使用順序表會好一些;

在插入、刪除操作使用的比較頻繁時,使用單鏈表會好一些。

2.從尾到頭列印單鏈表

void printheadtotail(listnode* plist)

while (plist)

printf("null\n");

}//遞迴方式

void printheadtotail(listnode* plist)

printf("%d->", plist->

data);

printheadtotail(plist->next);

}

3.刪除乙個無頭單鏈表的非尾節點

無頭單鏈表無法找到pos的前乙個節點,只能把pos後乙個節點的內容賦值給pos然後刪掉pos後乙個節點

void  erasenotail(listnode* pos)

else

}

4.在無頭單鏈表的乙個節點前插入乙個節點

先申請乙個節點插入到pos後面,然後再與pos的內容相交換

void

frontinsert(listnode* pos,datatype x)

5.單鏈表實現約瑟夫環

listnode*  josephring(listnode *plist, datatype k)

plist->

data

= plist->next->

data;

tmp = plist->next;

plist->next = plist->next->next;

free(tmp);

tmp =

null;

}return plist;

}

6.逆置/反轉單鏈表

listnode* reverse(listnode* plist)//逆置反轉單鏈表

return newhead;

}

7.單鏈表排序(氣泡排序&快速排序)

listnode *bubblesort(listnode *plist)//單鏈表排序(氣泡排序&快速排序)

else

cur = next;

next = next->next;

}tail = cur;

}cur = next = tail =

null;

}return plist;

}

8.合併兩個有序鍊錶,合併後依然有序

listnode *merge(listnode *plist1,listnode *plist2)

if (plist2 ==

null)

while (plist1 && plist2)

else

if (plist ==

null)

else

}if (plist1 ==

null)

else

return plist;

}

9.查詢單鏈表的中間節點,要求只能遍歷一次鍊錶

listnode *findmidnode(listnode *plist)

return slow;

}

10.查詢單鏈表的倒數第k個節點,要求只能遍歷一次鍊錶

listnode *findtailknode(listnode *plist,int k)

while (fast->next != null)

return slow;

}

C語言實現單鏈表面試題 高階

判斷單鏈表是否帶環?若帶環,求環的入口點 listnode judge band listnode plist 判斷單鏈表是否帶環?若帶環,求環的入口點?if fast next null fast next next null return null fast plist while fast s...

C語言實現單鏈表面試題(基礎篇)

順序表 1.記憶體中位址連續 2.長度不可變更 3.支援隨機查詢 可以在o 1 內查詢元素 4.適用於需要大量訪問元素的 而少量增添 刪除元素的程式 鍊錶 1.記憶體中位址非連續 2.長度可以實時變化 3.不支援隨機查詢 查詢元素時間複雜度o n 4.適用於需要進行大量增添 刪除元素操作而對訪問元素...

C語言實現單鏈表面試題(基礎篇)

順序表 1.記憶體中位址連續 2.長度不可變更 3.支援隨機查詢 可以在o 1 內查詢元素 4.適用於需要大量訪問元素的 而少量增添 刪除元素的程式 鍊錶 1.記憶體中位址非連續 2.長度可以實時變化 3.不支援隨機查詢 查詢元素時間複雜度o n 4.適用於需要進行大量增添 刪除元素操作而對訪問元素...