資料結構中單鏈表的那些事
在面試中面試資料結構中關於連結串列的基本操作,從未到頭列印單鏈表、逆置\翻轉單鏈表、合併兩個有序連結串列,合併後連結串列依然有序、查詢單鏈表的中間結點,只能遍歷一次單鏈表、刪除連結串列的倒數第K個結點,要求只能遍歷一次單鏈表等連結串列的操作,都是面試中常考題,所以這些是必須會的,實現如下
head.h
#pragma once #include<stdio.h> #include<stdlib.h> #include<assert.h> typedef int DataType; typedef struct ListNode { struct ListNode* _pNext; DataType data; }*PNode; void PrintSListFromTail2Head(PNode pHead); // 逆序列印單鏈表 void DeleteListNotTailNode(PNode pos); // 刪除連結串列的非尾結點,要求:不能遍歷連結串列 void InesrtPosFront(PNode pos, DataType data); // 在連結串列pos位置前插入值到data的結點 PNode FindMiddleNode(PNode pHead); // 查詢連結串列的中間結點,要求只能遍歷一次連結串列 PNode FindLastKNode(PNode pHead, int K); // 查詢連結串列的倒數第K個結點,要求只能遍歷一次連結串列 PNode DeleteLastKNode(PNode pHead, int K); // 刪除連結串列的倒數第K個結點,要求只能遍歷一次連結串列 void JosephCircle(PNode* pHead, const int M); // 用單鏈表實現約瑟夫環 void ReverseSList(PNode* pHead); // 連結串列的逆置--三個指標 PNode ReverseSListOP(PNode pHead); // 連結串列的逆置--頭插法 void BubbleSort(PNode pHead); // 用氣泡排序思想對單鏈表進行排序 PNode MergeSList(PNode pHead1, PNode pHead2); // 合併兩個有序單鏈表,合併後依然有序 int IsSListCross(PNode pHead1, PNode pHead2); // 判斷兩個單鏈表是否相交---連結串列不帶環 PNode GetCorssNode(PNode pHead1, PNode pHead2); // 求兩個單鏈表相交的交點---連結串列不帶環
head.c
#include"head.h" void PrintSListFromTail2Head(PNode pHead) // 逆序列印單鏈表 { assert(pHead); PNode pNewNode = pHead; if (NULL == pHead) { return; } else if (pNewNode) { PrintSListFromTail2Head(pNewNode->_pNext); } printf("%d", pNewNode->data); return; } void DeleteListNotTailNode(PNode pos) // 刪除連結串列的非尾結點,要求:不能遍歷連結串列 { PNode p_Cur = pos->_pNext; pos->data =p_Cur->data; pos->_pNext = p_Cur->_pNext; free(p_Cur); p_Cur = NULL; } void InesrtPosFront(PNode pos, DataType data) // 在連結串列pos位置前插入值到data的結點 { PNode p = pos->_pNext; //放置pos位置後面的指標 pos ->_pNext = (PNode)BuyNewNode(pos->data); //新建立的結點放在pos後面,並且新建立的結點的data是pos位置的data pos->_pNext->_pNext = p; //將原來pos後面的結點連線起來 pos->data = data; //將需要插入的資料元素放在pos的位置
}
PNode FindMiddleNode(PNode pHead) // 查詢連結串列的中間結點,要求只能遍歷一次連結串列 { assert(pHead); if (NULL == pHead->_pNext ) { return pHead; } PNode Fast = pHead; //建立一個快指標,每次走兩步 PNode Slow = pHead; //建立一個慢指標,一次走一步 while (Fast && Fast->_pNext) //判斷元素個數是奇數和偶數時,返回中間結點 { Fast = Fast->_pNext->_pNext; Slow = Slow->_pNext; } return Slow; //最後返回慢指標剛好走到中間結點 } PNode FindLastKNode(PNode pHead, int K) // 查詢連結串列的倒數第K個結點,要求只能遍歷一次連結串列 { assert(pHead); if (NULL == pHead || K<=0) //判空連結串列和輸入的合法性 { return NULL; } PNode Fast = pHead; PNode Slow = pHead; while (K--) { Fast = Fast->_pNext; //快指標先向後走k步,然後慢指標和快指標一起以相同的速度向後走 } while (Fast) { Fast = Fast->_pNext; Slow = Slow->_pNext; } return Slow; } PNode DeleteLastKNode(PNode pHead, int K) // 刪除連結串列的倒數第K個結點,要求只能遍歷一次連結串列 { assert(pHead); if (NULL == pHead) { return NULL; } PNode Fast = pHead; PNode Slow = pHead; PNode Cur_Node = NULL; while (K--) { Fast = Fast->_pNext; //快指標先向後走k步,然後慢指標和快指標一起以相同的速度向後走 } while (Fast) { Fast = Fast->_pNext; Cur_Node = Slow; Slow = Slow->_pNext; Cur_Node->_pNext = Slow->_pNext; } return pHead; } void JosephCircle(PNode* pHead, const int M) // 用單鏈表實現約瑟夫環 { PNode Cur_node = NULL; PNode Del_node = NULL; int count = 0; assert(pHead); if (NULL == pHead || M <= 0) { return; } Cur_node = *pHead; while (Cur_node->_pNext) { Cur_node = Cur_node->_pNext; } Cur_node->_pNext = *pHead; Cur_node = *pHead; while (Cur_node->_pNext != Cur_node) { count = M; while (--count) { Cur_node = Cur_node->_pNext; } Del_node = Cur_node->_pNext; Cur_node->_pNext = Del_node->_pNext; free(Del_node); Del_node = NULL; } } void ReverseSList(PNode* pHead) // 連結串列的逆置--三個指標 { PNode Pre_node = NULL; PNode Cur_node = NULL; PNode Next_node = NULL; assert(pHead); Cur_node = *pHead; while (Cur_node) { Pre_node = Cur_node; Cur_node = Cur_node->_pNext; Pre_node->_pNext = Next_node; Next_node = Pre_node; } } PNode ReverseSListOP(PNode pHead) // 連結串列的逆置--頭插法 { PNode Cur_node = NULL; PNode Next_node = NULL; assert(pHead); if (NULL == pHead || NULL == pHead->_pNext) { return NULL; } while (pHead) { Cur_node = pHead; pHead = pHead->_pNext; Cur_node->_pNext = Next_node; Next_node = Cur_node; } pHead = Next_node; return pHead; } void BubbleSort(PNode pHead) // 用氣泡排序思想對單鏈表進行排序,從小到大排序 { PNode Tail = NULL; PNode P_Cur = pHead; int flag = 0; if (NULL == pHead || NULL == pHead->_pNext) { return; } while (Tail != pHead) //先判斷單鏈表是否是有序的,按照排序結果,如果一趟排序,標記flag沒有發生變化就直接列印單鏈表 { P_Cur = pHead; flag = 0; } while (P_Cur!=Tail) { while (P_Cur->_pNext!=Tail) { if (P_Cur->data > P_Cur->data) { DataType tmp = P_Cur->data; P_Cur->data = P_Cur->_pNext->data; P_Cur->_pNext->data = tmp; flag = 1; } P_Cur = P_Cur->_pNext; } Tail = P_Cur; if (0 == flag) { return; } } } PNode MergeSList(PNode pHead1, PNode pHead2) // 合併兩個有序單鏈表,合併後依然有序 { PNode P_NewNode = NULL; pHead1 = pHead1->_pNext; pHead2 = pHead2->_pNext; P_NewNode = pHead1; while (pHead1 && pHead2) //兩個連結串列首先都不為空,然後判斷兩個連結串列的data的大小 { if (pHead1->data > pHead2->data) { P_NewNode = P_NewNode->_pNext; P_NewNode->data = pHead2->data; pHead2 = pHead2->_pNext; } else { P_NewNode = P_NewNode->_pNext; P_NewNode->data = pHead1->data; pHead1 = pHead1->_pNext; } } P_NewNode->_pNext = pHead1 ? pHead1 : pHead2; //判斷連結串列是否一個已經為空,直接將另一個連結串列的內容連結在後面 free(pHead2); return P_NewNode; } int IsSListCross(PNode pHead1, PNode pHead2) // 判斷兩個單鏈表是否相交---連結串列不帶環 { PNode p1 = pHead1; PNode p2 = pHead2; int p1_Size = 0; //pHead1的大小,設定計數器計數 int p2_Size = 0; //pHead2的大小,設定計數器計數 int k = 0; //PHead1和PHead大小比較相差的步數 if (NULL == p1 || NULL == p2) //判斷連結串列是否為空,如果為空就返回0,所以不想交 { return 0; } while (p1) //連結串列1不為空繼續計數 { p1_Size++; p1 = p1->_pNext; } while (p2) //連結串列的大小 { p2_Size++; p2 = p2->_pNext; } if (p1_Size > p2_Size) { k = p1_Size - p2_Size; while (k--) { p1->_pNext; } p2->_pNext; if (p1->data == p2->data) { return 1; } } if (p1_Size < p2_Size) { k = p2_Size - p1_Size; while (k--) { p2->_pNext; } p1->_pNext; } if (p1->data == p2->data) { return 1; }
}
PNode GetCorssNode(PNode pHead1, PNode pHead2) // 求兩個單鏈表相交的交點---連結串列不帶環
{
PNode p1 = pHead1;
PNode p2 = pHead2;
int p1_Size = 0; //pHead1的大小,設定計數器計數
int p2_Size = 0; //pHead2的大小,設定計數器計數
int k = 0; //PHead1和PHead大小比較相差的步數
if (NULL == p1 || NULL == p2) //判斷連結串列是否為空,如果為空就返回0,所以不想交
{
return NULL;
}
while (p1) //連結串列1不為空繼續計數
{
p1_Size++;
p1 = p1->_pNext;
}
while (p2) //連結串列的大小
{
p2_Size++;
p2 = p2->_pNext;
}
if (p1_Size > p2_Size)
{
k = p1_Size - p2_Size;
while (k--)
{
p1->_pNext;
}
p2->_pNext;
if (p1->data == p2->data)
{
return p1;
}
}
if (p1_Size < p2_Size)
{
k = p2_Size - p1_Size;
while (k--)
{
p2->_pNext;
}
p1->_pNext;
}
if (p1->data == p2->data)
{
return p1;
}
else
{
return NULL;
}
}
相關推薦
資料結構中單鏈表的那些事
在面試中面試資料結構中關於連結串列的基本操作,從未到頭列印單鏈表、逆置\翻轉單鏈表、合併兩個有序連結串列,合併後連結串列依然有序、查詢單鏈表的中間結點,只能遍歷一次單鏈表、刪除連結串列的倒數第K個結點,要求只能遍歷一次單鏈表等連結串列的操作,都是面試中常考題,所
C 資料結構中單鏈表基本操作
C中的typedef C中的typedef關鍵字作用是為一種資料型別定義一個新名字,這樣做的目的有兩個,一是給變數定義一個易記且意義明確的新名字,如: typedef unsigned char BYTE; 把unsigned char型別自命名為BYTE。另一個目的是
資料結構中單鏈表中的 頭插法和尾插法
正在學習資料結構中的連結串列,在有沒有頭節點的問題上的 頭插法跟尾插法一直模糊。。。。。 作為一個新手,整理了一下在有節點時的 頭插法跟尾插法 頭插法程式碼: int InsertHread(LinkList &L,int e) { LinkList tamp
資料結構中單鏈表的實現+單鏈表的C語言實現原始碼
線性表(List):零個或多個數據元素的有限序列。線性表的抽象資料型別。 線性表的順序儲存: 優點:無須為表示表中元素的邏輯關係而額外的儲存空間,可以快速的取表中任意位置的元素。 缺點:插入和刪除操作需要轉移大量元素,線性表的長度較大時,難以確定儲存空間的容量, 造成儲存空
資料結構之單鏈表插入刪除操作
#include<iostream> using namespace std; typedef struct LNode { int data; struct LNode *next; }LNode; void createListR(LNode *C, int a[], int n
重學資料結構(一)單鏈表
最近在重新學習資料結構,特此記錄學習過程,碼農再次上線 關於單鏈表的一些基本操作,以下為基本思路程式碼 首先看一張直觀圖 連結串列的結構體定義如下(為簡便,這裡的ElemType採用int): //單鏈表 typedef struct LNode {
C#資料結構之單鏈表(LinkList)例項詳解
本文例項講述了C#資料結構之單鏈表(LinkList)實現方法。分享給大家供大家參考,具體如下: 這裡我們來看下“單鏈表(LinkList)”。在上一篇《C#資料結構之順序表(SeqList)例項詳解》的最後,我們指出了:順序表要求開闢一組連續的記憶體空間,而且插入/刪除元素時,為了保證元素的順序
演算法與資料結構之單鏈表
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
資料結構中 線性表,棧,佇列,演算法之間的聯絡與區別
一。連結串列為什麼需要 在程式中,經常需要將一種(通常是同為某個型別的)資料元素作為整體管理和使用,需要建立這種元素組,用變數記錄他們,傳進傳出函式等。一組元素可能發生變化(像增加或刪除元素。)
【資料結構】單鏈表的逆序輸出
即:將一個已經建立好的單鏈表進行指標域的改變 今天突然被問到單鏈表逆序的問題,弄了好久才看出別人的程式有啥問題,就重新寫了一遍。 今天才在CSDN客戶端上看到美團的面試題是氣泡排序。 一個看似簡單的問題難倒很多人,所以簡單的不要因為他簡單就忽視它,人們在簡單的問題上越容易犯錯!
資料結構回顧-------單鏈表
單鏈表,用指標來實現的線性表 為了方便操作,我們定義一個頭指標來操作連結串列 結構體為Node 一個整型data,一個Node指標next指向下一個節點 封裝類為LinkList 連結串列的各個操作具體看類的函式即可。 /*
資料結構之單鏈表
從今天起開始資料結構系列的分享,今天分享的是單鏈表。單鏈表大概是大概是每個資料結構 初學者的必經之路,下面結合一個小小的工程深入學習單鏈表的使用–簡易客戶管理系統。 ps:如果還不清楚單鏈表是什麼的小夥伴自行百度,在此不在贅述 專案結構 如
初識資料結構之單鏈表——Java語言
import java.util.Scanner; public class LinkList{ ListNode H = new ListNode(0); /** *尾插法建立連結串列 */ public void creatLinkList(){ ListNode f
資料結構與演算法的那些事
先佔坑,再補充。 常用演算法: (1)排序:快排、歸併排序、插入排序、希爾排序、桶排序; (2)分治演算法(divide-and-conquer),回溯演算法,貪婪演算法,動態規劃(DP); (3)二分查詢(binary search); 一、排序演算法 演
【資料結構】單鏈表的實現
單鏈表是線性錶鏈式儲存的一種形式,其中的結點一般含有兩個域,一個是存放資料資訊的info域,另一個是指向該結點後繼結點存放地址的指標next域。一個單鏈表必須要有一個首指標指向連結串列中的第一個結點。 單鏈表要掌握以下幾種操作: 1、建立一個空的單鏈表。 2、輸出單鏈表
【資料結構】單鏈表-----基本操作
刪除指定位置的節點 void Erase(pList * pplist, pNode pos) { assert(pplist != NULL); assert(pos != NULL); if (*pplist == pos)//如果指向第一個節點
資料結構:單鏈表的就地逆置
6-1 帶頭結點的單鏈表就地逆置(10 分) 本題要求編寫函式實現帶頭結點的單鏈線性表的就地逆置操作函式。L是一個帶頭結點的單鏈表,函式ListReverse_L(LinkList &L)要求在不新開闢節點的前提下將單鏈表中的元素進行逆置,如原單鏈表元素依次為1
【資料結構】單鏈表(無頭單向非迴圈連結串列)各個介面的實現
順序表存在的問題: 中間/頭部的插入刪除,時間複雜度為O(N) 增容需要申請新空間,拷貝資料,釋放舊空間。會有不小的消耗 增容一般是呈2倍的增長,勢必會有一定的空間浪費。 例如當前容量為100,滿了以後增容到200,如果再繼續插入了5個數據,後面沒有資料插入了,
【資料結構】單鏈表的運用 多項式加法
#include<stdio.h> #include<stdlib.h> struct mono{ int e; int c; }; struct node{ mono data; node * next; }; str
資料結構之單鏈表(二)
//判斷單鏈表是否有環:思路:設定兩個"指標",一個走一步,一個走兩步,若存在環,則一定會存在有相交的位置點 public boolean isLoop(Linklist LNode){ Node p=head.next; Node q=h