1. 程式人生 > >單鏈表的基本操作及連結串列面試題

單鏈表的基本操作及連結串列面試題

單鏈表的基本操作及連結串列面試題


程式程式碼如下:


LinkList.h


#ifndef __LINKLIST_H__ 
#define __LINKLIST_H__ 

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int DataType;
typedef struct Node
{
	DataType data;
	struct Node* next;
}Node, *pNode, List, *pList;

void InitLinkList
(pList* pplist); pNode BuyNode(DataType d); void DestroyLinkList(pList* pplist); void PushBack(pList* pplist, DataType d); void PopBack(pList* pplist); void PushFront(pList* pplist, DataType d); void PopFront(pList* pplist); pNode Front(pNode pHead); pNode Back(pNode pHead); pNode Find(pList plist, DataType d)
; //在指定位置之前插入一個值 void Insert(pList* pplist, pNode pos, DataType d); //指定位置刪除 void Erase(pList* pplist, pNode pos); void Remove(pList* pplist, DataType d); void RemoveAll(pList* pplist, DataType d); void EraseNotTailNode(pNode pos); void PrintLinkList(pList plist); int GetListLength(pList plist); //連結串列面試題
//1. 逆序列印單項鍊表 void PrintTailToHead(pList plist); //2.獲取單鏈表的最後一個節點 pNode SListBack(pList plist); // 在單鏈表非頭結點前插入新節點,要求不能遍歷連結串列 void InsertPosFront(pNode pos, DataType data); // 用氣泡排序對單鏈表進行排序 void BubbleSort(pNode* pHead); // 查詢單鏈表的中間結點,要求只能遍歷一次連結串列 pNode FindMiddleNode(pNode pHead); // 查詢單鏈表的倒數第K個結點,要求只能遍歷一次連結串列 pNode FindLastKNode(pNode pHead, int K); // 單鏈表的逆置 void ReverseList(pNode* pHead); pNode ReverseListOP(pNode pHead); // 合併兩個有序連結串列,合併成功後依然有序 pNode MergeList(pNode pHead1, pNode pHead2); // 用單鏈表模擬實現約瑟夫環 pNode JosephCircle(pNode pHead, int M); // 檢測單鏈表是否帶環 pNode HasListCircle(pNode pHead); // 求環的長度 int GetCircleLen(pNode pHead); // 求環的入口點 pNode GetEnterNode(pNode pHead, pNode pMeetNode); // 判斷兩個單鏈表是否相交(連結串列不帶環) int IsListCross(pNode pHead1, pNode pHead2); // 若相交,求交點 pNode GetCrossNode(pNode pHead1, pNode pHead2); // 檢測兩個連結串列是否相交,連結串列可能帶環 pNode IsListCrossWithCircle(pNode pHead1, pNode pHead2); #endif //__LINKLIST_H__

LinkList.c

#include "Linklist Interface.h"

void InitLinkList(pList* pplist)
{
	assert(pplist);
	*pplist = NULL;
}

pNode BuyNode(DataType d)
{
	pNode newNode = (pNode)malloc(sizeof(Node));
	/*if (newNode == NULL)
	{
		perror("malloc");
		exit(EXIT_FAILURE);
	}*/
	if (NULL == newNode)
	{
		assert(0);
		return NULL;
	}
	newNode->data = d;
	newNode->next = NULL;
	newNode->rand = NULL;
	return newNode;
}

void DestroyLinkList(pList* pplist)
{
	assert(pplist);
	pNode cur = *pplist;
	while (cur)
	{
		pNode del = cur;
		cur = cur->next;
		free(del);
		del = NULL;
	}
	*pplist = NULL;
}

void PushBack(pList* pplist, DataType d)
{
	assert(pplist);
	pNode newNode = BuyNode(d);
	pNode tail = *pplist;
	if (*pplist == NULL)
	{
		*pplist = newNode;
		return;
	}
	while (tail->next)
	{
		tail = tail->next;
	}
	tail->next = newNode;
}

void PopBack(pList* pplist)
{
	assert(pplist);
	pNode tail = *pplist;
	pNode pre = NULL;
	if (*pplist == NULL)
		return;
	if (tail->next == NULL)
	{
		free(*pplist);
		*pplist = NULL;
		return;
	}
	while (tail->next != NULL)
	{
		pre = tail;
		tail = tail->next;
	}
	free(tail);
	pre->next = NULL;
}

void PushFront(pList* pplist, DataType d)
{
	assert(pplist);
	if (*pplist == NULL)
		*pplist = BuyNode(d);
	else
	{
		pNode newNode = BuyNode(d);
		newNode->next = *pplist;
		*pplist = newNode;
	}
}

void PopFront(pList* pplist)
{
	assert(pplist);
	pNode cur = *pplist;
	if (*pplist == NULL)
		return;
	*pplist = cur->next;
	free(cur);
	cur = NULL;
}

pNode Front(pNode pHead)
{
	if (NULL == pHead)
		return NULL;
	return pHead;
}

pNode Back(pNode pHead)
{
	if (NULL == pHead)
		return NULL;
	while (NULL != pHead->next)
		pHead = pHead->next;
	return pHead;
}

pNode Find(pList plist, DataType d)
{
	while (plist)
	{
		if (d == plist->data)
			return plist;
		plist = plist->next;
	}
	return NULL;
}

//在指定位置之前插入一個值 
void Insert(pList* pplist, pNode pos, DataType d)
{
	assert(pplist);
	assert(pos);
	if (*pplist == NULL)
		PushFront(pplist, d);
	else
	{
		pNode cur = NULL;
		pNode tail = *pplist;
		while (tail->next != pos)
			tail = tail->next;
		cur = BuyNode(d);
		tail->next = cur;
		cur->next = pos;
	}
}
//指定位置刪除 
void Erase(pList* pplist, pNode pos)
{
	assert(pplist);
	assert(pos);
	if (*pplist == NULL)
		return;
	if ((NULL == (*pplist)->next) || (*pplist == pos))
		PopFront(pplist);
	else
	{
		pNode tmp = *pplist;
		while (tmp->next != pos)
			tmp = tmp->next;
		tmp->next = pos->next;
		free(pos);
		pos = NULL;
	}
}

void Remove(pList* pplist, DataType d)
{
	assert(pplist);
	if (NULL == *pplist)
		return;
	if (d == (*pplist)->data)
		PopFront(pplist);
	else
	{
		pNode tmp = *pplist;
		while (tmp->next->data != d)
			tmp = tmp->next;
		pNode pos = tmp->next;
		tmp->next = pos->next;
		free(pos);
		pos = NULL;
		//pNode pos = Find(*pplist, d);
	}
}

void RemoveAll(pList* pplist, DataType d)
{
	assert(pplist);
	pNode tmp = *pplist;
	pNode cur = *pplist;
	if (NULL == *pplist)
		return;
	if (d == (*pplist)->data)
		PopFront(pplist);
	while (cur)
	{
		if (d == cur->data)
		{
			tmp->next = cur->next;
			free(cur);
			cur = tmp->next;
		}
		else
		{
			tmp = cur;
			cur = cur->next;
		}
	}
}

void EraseNotTailNode(pNode pos)
{
	assert(pos);
	pNode del = pos->next;
	if (NULL == del)
		return;
	pos->data = del->data;
	pos->next = del->next;
	free(del);
	del = NULL;
}

void PrintLinkList(pList plist)
{
	pNode tmp = plist;
	while (tmp)
	{
		printf("%d-->", tmp->data);
		tmp = tmp->next;
	}
	printf("NULL\n");
}

int GetListLength(pList plist)
{
	int count = 0;
	while (plist)
	{
		count++;
		plist = plist->next;
	}
	return count;
}
//連結串列面試題 

//1. 逆序列印單項鍊表 
void PrintTailToHead(pList plist)
{
	if (plist == NULL)
	{
		printf("NULL");
		return;
	}
	else
	{
		PrintTailToHead(plist->next);
		printf("<--%d", plist->data);
	}
	//printf("\n");
}
//2.獲取單鏈表的最後一個節點
pNode SListBack(pList plist)
{
	if (NULL == plist)
		return NULL;
	while (plist->next)
	{
		plist = plist->next;
	}
	return plist;
}

// 在單鏈表非頭結點前插入新節點,要求不能遍歷連結串列 
void InsertPosFront(pNode pos, DataType data)
{
	pNode pNewNode;
	pNode cur;
	DataType tmp = 0;

	assert(pos);
	if (NULL == pos)
		return;

	pNewNode = BuyNode(data);
	cur = pos;
	pNewNode->next = cur->next;
	cur->next = pNewNode;

	tmp = pNewNode->data;
	pNewNode->data = cur->data;
	cur->data = tmp;
}

// 用氣泡排序對單鏈表進行排序 
void BubbleSort(pNode* pHead)
{
	pNode cur = (*pHead);
	pNode tail = NULL;
	DataType tmp = 0;

	if (NULL == (*pHead) || NULL == (*pHead)->next)
		return;

	while (cur != tail)
	{
		while (cur->next != tail)
		{
			if (cur->data > cur->next->data)
			{
				tmp = cur->next->data;
				cur->next->data = cur->data;
				cur->data = tmp;
			}
			cur = cur->next;
		}
		tail = cur;
		cur = (*pHead);
	}
}

// 查詢單鏈表的中間結點,要求只能遍歷一次連結串列 
pNode FindMiddleNode(pNode pHead)
{
	pNode fast = pHead;
	pNode slow = pHead;

	if (NULL == pHead)
		return NULL;

	while (fast)
	{
		if (fast->next)
			fast = fast->next->next;
		else
		{
			fast = fast->next;
			break;
		}
		slow = slow->next;
	}
	return slow;
}

// 查詢單鏈表的倒數第K個結點,要求只能遍歷一次連結串列 
pNode FindLastKNode(pNode pHead, int K)
{
	pNode fast = pHead;
	pNode slow = pHead;

	if (NULL == pHead || 0 == K)
		return NULL;

	while(K--)
		fast = fast->next;
	while (fast)
	{
		fast = fast->next;
		slow = slow->next;
	}
	return slow;
}

// 單鏈表的逆置 
void ReverseList(pNode* pHead)
{
	pNode cur = (*pHead)->next;
	pNode tmp = NULL;

	assert(pHead);

	if (NULL == (*pHead))
		return;
	(*pHead)->next = NULL;

	while (cur)
	{
		tmp = cur;
		cur = cur->next;
		tmp->next = (*pHead);
		(*pHead) = tmp;
	}
}

pNode ReverseListOP(pNode pHead)
{
	pNode cur = pHead;
	pNode NewHead = NULL;
	pNode tmp = NULL;

	if (NULL == pHead || NULL == pHead->next)
		return NULL;

	while (cur)
	{
		tmp = cur->next;
		cur->next = NewHead;
		NewHead = cur;
		cur = tmp;
	}
	return NewHead;

}

// 合併兩個有序連結串列,合併成功後依然有序 
pNode MergeList(pNode pHead1, pNode pHead2)
{
	pNode pNewNode = NULL;
	pNode pNewHead = NULL;
	pNode p1 = pHead1;
	pNode p2 = pHead2;

	if (NULL == p1)
		return p2;
	if (NULL == p2)
		return p1;

	if (p1->data > p2->data)
	{
		pNewNode = p2;
		p2 = p2->next;
		pNewHead = pNewNode;
	}
	else
	{
		pNewNode = p1;
		p1 = p1->next;
		pNewHead = pNewNode;
	}

	while (NULL != p1 && NULL != p2)
	{
		if (p1->data > p2->data)
		{
			pNewNode->next = p2;
			p2 = p2->next;
			pNewNode = pNewNode->next;
		}
		else
		{
			pNewNode->next = p1;
			p1 = p1->next;
			pNewNode = pNewNode->next;
		}
	}

	if (NULL == p1)
	{
		pNewNode->next = p2;
		return pNewHead;
	}
	if (NULL == p2)
	{
		pNewNode->next = p1;
		return pNewHead;
	}
}

// 用單向迴圈連結串列模擬實現約瑟夫環 
pNode JosephCircle(pNode pHead, int M)
{
	int num;
	pNode pre = NULL;
	pNode cur = pHead;
	if (NULL == pHead)
		return NULL;
	if (1 != M)
	{
		while (cur->next != cur)
		{
			num = M;
			while (--num)
			{
				pre = cur;
				cur = cur->next;
			}
			pre->next = cur->next;
			free(cur);
			cur = pre->next;
		}
		return cur;
	
            
           

相關推薦

單鏈基本操作連結串列試題

單鏈表的基本操作及連結串列面試題 程式程式碼如下: LinkList.h #ifndef __LINKLIST_H__ #define __LINKLIST_H__ #include <stdio.h> #include <stdlib.

單鏈基本操作(刪除連結串列中最大元素)

題目描述: 設計一個演算法,刪除一個單鏈表L中元素值最大的節點(假設這樣的節點唯一) 解題思路: 在單鏈表中刪除一個節點先要找到它的前驅節點,用指標p掃描整個單鏈表,pre指向節點p的前驅節點,在掃描時用maxp指向data域值最大的節點,maxpre指向maxp所指節點的前驅節點,當連

C++ 單鏈表基本操作分析與實現 連結串列   連結串列是一種物理儲存單元上非連續、非順序的儲存結構,資料元素的邏輯順序是通過連結串列中的指標連結次序實現的。連結串列由一系列結點(連結串列中每一個元素稱為結點)組成,結

連結串列   連結串列是一種物理儲存單元上非連續、非順序的儲存結構,資料元素的邏輯順序是通過連結串列中的指標連結次序實現的。連結串列由一系列結點(連結串列中每一個元素稱為結點)組成,結點可以在執行時動態生成。每個結點包括兩個部分:一個是儲存資料元素的資料域,另一個是儲存下一個結點地址的指標域。 相比於線性表

資料結構之連結串列(1):單鏈基本操作

1.前言 1.1宣告 文章中的文字可能存在語法錯誤以及標點錯誤,請諒解; 如果在文章中發現程式碼錯誤或其它問題請告知,感謝! 2.關於連結串列 2.1什麼是連結串列 連結串列可以看成一種在物理儲存單元上的非連續、非順序儲存的資料結構,該資

完成雙鏈的一些基本操作連結串列的建立,雙向輸出,插入,刪除)

#include "stdafx.h" #include<stdlib.h> #include<stdio.h> #include<string.h> typedef struct dlink_node  {     int info;

單鏈 基本操作(元素遞增排序)

題目描述: 有一個帶頭節點的單鏈表L(至少有一個數據節點),設計一個演算法使其元素遞增有序排列。 解題思路: 由於單鏈表L中有一個以上的資料節點,首先構造一個只含有頭結點和首節點的有序單鏈表(只含有一個數據節點的單鏈表一定是有序的),然後掃描單鏈表L餘下的節點(由P指向),在有序單鏈表中

單鏈 簡單題(單鏈基本操作

題目描述: 有一個帶頭結點的單鏈表L=(a1,b1,a2,b2,......an,bn),設計一個演算法將其拆分成兩個帶頭結點的單鏈表L1和L2,其中L1=(a1,a2,a3...an),L2=(b1,b2,b3....bn),要求L1使用L的頭結點。 解題思路: 利用原單鏈表L中的所有

C 資料結構中單鏈基本操作

C中的typedef C中的typedef關鍵字作用是為一種資料型別定義一個新名字,這樣做的目的有兩個,一是給變數定義一個易記且意義明確的新名字,如: typedef unsigned char BYTE; 把unsigned char型別自命名為BYTE。另一個目的是

建立一個單鏈,並刪除連結串列中值為W的元素

#include<iostream> #include<algorithm> #include<string.h> #include<stdio.h> #include<malloc.h> using namespace std; typede

建立單鏈並原地將連結串列逆序

#include<iostream> #include<stdio.h> using namespace std; #define MAXSIZE 5 #define ERROR -1; #define CORRECT 1; typedef struct List{

【資料結構】單鏈-----基本操作

刪除指定位置的節點 void Erase(pList * pplist, pNode pos) { assert(pplist != NULL); assert(pos != NULL); if (*pplist == pos)//如果指向第一個節點

c++學習筆記—單鏈基本操作的實現

用c++語言實現的單鏈表基本操作,包括單鏈表的建立(包括頭插法和尾插法建表)、結點的查詢、刪除、排序、列印輸出、逆置、連結串列銷燬等基本操作。 IDE:vs2013 具體實現程式碼如下: #include "stdafx.h" #include <malloc.h

單鏈基本操作java實現

單鏈表基本操作 - java實現 1.單鏈表學習了好久,今天終於有時間寫一下了,帶頭結點的單鏈表上的基本操作,Java實現。 (1) 先來個介面 public interface IList { public void clear(); //清空連結串列 publi

Java單鏈基本操作(七)--排序

單鏈表的插入排序比陣列麻煩,因為每次都都要從頭節點開始往後遍歷,頭節點也需要單獨處理 package listnode; /** * @author Gavenyeah * @date St

Java單鏈基本操作(八)--合併兩個有序單鏈

package listnode; /** * @author Gavenyeah * @date Start_Time:2016年4月1日 下午15:01:47 * @date End_Ti

c++實現單鏈基本操作

程式媛決定好好學習寫程式碼 連結串列是一種物理儲存單元上非連續、非順序的儲存結構,資料元素的邏輯順序是通過連結串列中的指標連結次序實現的。連結串列由一系列結點(連結串列中每一個元素稱為結點)組成,結點可以在執行時動態生成。每個結點包括兩個部分:一個是儲存資料元素的資料域,

單鏈的建立(靜態連結串列,動態連結串列)

       連結串列是一種很重要的資料結構,在實際工作中也有著很多的應用,這次我們先討論一下最簡單的單鏈表。        關於單鏈表的操作有很多,當然最基本的就是要建立一個單鏈表,對於單鏈表來說,可以按照型別分為靜態連結串列和動態連結串列。 1.靜態連結串列 靜態連結串

無頭結點單鏈基本操作

動態順序表 linklist.h #pragma once #include <stdio.h> #include <assert.h> #include <malloc.h> #include <stdlib.h&

單鏈基本操作的C語言實現(鏈式儲存結構)

#include<stdio.h> #include<stdlib.h> typedef int DataType; typedef struct Node{ DataType data; struct Node *next; }

單鏈基本操作(1)

單鏈表基本操作 建立 建立 頭插入載入 尾插入載入 建立空連結串列 建立一個單鏈表,且為空表,並且返回連結串列 建立結構型別,在CS.c檔案中 typedef struct node{ int data; struc