1. 程式人生 > >單鏈表,頭插法,尾插法各種函式詳解

單鏈表,頭插法,尾插法各種函式詳解

一:LinkList.cpp檔案

#include <stdio.h>
#include <malloc.h>         //malloc函式 用了<stdlib.h>中的 <malloc.h>標頭檔案
typedef int ElemType;       //自定義型別 使 ElemType 為 int型
typedef struct LNode  		//定義單鏈表結點型別
{
	ElemType data;
	struct LNode *next;		//定義連結串列結點型別的指標 指向後繼結點
} LinkList;
/*  連結串列中 不同對指標變數的不同引用的解釋
    在main()函式裡 建立的是 LinkList *L;
    LinkLIst型別的指標變數 *L,變數L本身有地址,
    作為指標變數也會儲存 指向元素的地址
    如 L=(LinkList *)malloc(sizeof(LinkList));  	//建立頭結點
    L指向了 通過malloc 函式從記憶體裡動態獲取的一塊區域的 地址
    在主函式讀取CreateListR(L,a,n);之前L沒有儲存地址不能用 *L
    我的另外一篇轉載部落格  https://blog.csdn.net/Waybyway/article/details/83385551
    在C語言裡沒有C++所謂的“按引用傳遞”,解釋了C 和C++ 的不同

    連結串列所有改變連結串列函式長度的函式如
    一: 頭插法,尾插法建立,初始化,銷燬,插入,刪除元素等函式用的引數是(LinkList *&L)
    *&L表示 *是間接運算子 對&L(L本身的地址)間接運算,

    二:其他函式引數都是(LinkList *L)


*/
/*單鏈表 頭插法解釋
    在主函式main()中 的指標Linklist *L用來建立連結串列;
    L為頭結點,首地址存在這個裡面了
    L=(LinkList *)malloc(sizeof(LinkList));  	//建立頭結點
    在輸入之前現將他的指向置為 空NULL
    通過malloc(sizeof(LinkList))動態分配sizeof(LinkList)的大小的空間
    malloc函式的預設返還型別使 void型別,轉換成 (LinkList *)型別
    這樣就建立了一個新結點 S
    s->data=a[i]; s結點的data值被賦值為 a[i];

    由於頭結點 L->next=NULL,所以 s->next=L->next;
    s->next 的指向也是NULL

    L->next=S; 頭結點 L指向了 第一個S (這個S記作 S_0)
    這樣頭結點L就在 所有新結點的前面,最後使S_0結尾 指向為空
    for(), 產生下一個 S_1
    同樣 S_1 的data被賦值,s->next=L->next;
    上一步 L指向 S_0即上一個 S,這樣S_1也指向了S_0
    L->next=s;  L這樣就指向了 S_1
    總之 S_0指向空,新的 S結點指向前一個 S結點
    頭結點L就在 所有新結點的前面,最後使S_0結尾 指向為空
    最後生成的連結串列就是這樣 連結串列 數值序列是 陣列序列的逆序
    L -> S_(N-1) -> S_(N-2) -> S_(N-3)……………… -> S_(1) -> S_(0) -> NULL
*/
void CreateListF(LinkList *&L,ElemType a[],int n)
//頭插法建立單鏈表,將長度為N的陣列 a[]建立為連結串列
{
	LinkList *s;int i;
	L=(LinkList *)malloc(sizeof(LinkList));  	//建立頭結點
	L->next=NULL;
	for (i=0;i<n;i++)
	{
		s=(LinkList *)malloc(sizeof(LinkList));//建立新結點
		s->data=a[i];
		s->next=L->next;			//將*s插在原開始結點之前,頭結點之後
		L->next=s;
	}
}
/*尾插法,部分解釋與頭插法不再敘述
    L為頭結點 ,指向為空
    r=L; R 的指向也為空,R 的位置與L並列
    產生新結點 S ,data被賦值為a[i]
    r->next=s;			//將*s插入*r之後
    R 的位置與L並列
    頭結點L 指向 新產生的S結點 記作S_0
    r=s;  R 的位置與S_0並列
    S_1產生 ,S_1的data被賦值
    因為原來R與S_0並列,所以 r->next=s;
    這樣S_0就指向了S_1
    最後一個S_(n-1)產生,R與他並列
    最後指向空NULL
    總之 R指標每次與新產生結點並列,讓新結點指向下一個新結點
    到最後一個結點 指向空
    所以尾插法建立的連結串列 數值序列是 陣列序列
    L -> S_(0) -> S_(1) -> S_(2)………………  -> S_(N-2)-> S_(N-1) -> NULL
*/
void CreateListR(LinkList *&L,ElemType a[],int n)
//尾插法建立單鏈表
{
	LinkList *s,*r;int i;
	L=(LinkList *)malloc(sizeof(LinkList));  	//建立頭結點
	L->next=NULL;
	r=L;					//r始終指向終端結點,開始時指向頭結點
	for (i=0;i<n;i++)
	{
		s=(LinkList *)malloc(sizeof(LinkList));//建立新結點
		s->data=a[i];
		r->next=s;			//將*s插入*r之後
		r=s;
	}
	r->next=NULL;			//終端結點next域置為NULL
}
void InitList(LinkList *&L)
{
	L=(LinkList *)malloc(sizeof(LinkList));  	//建立頭結點
	L->next=NULL;
}
void DestroyList(LinkList *&L)
{
	LinkList *p=L,*q=p->next;
	while (q!=NULL)
	{	free(p);
		p=q;
		q=p->next;
	}
	free(p);	//此時q為NULL,p指向尾結點,釋放它
}
bool ListEmpty(LinkList *L)
{
	return(L->next==NULL);
}
int ListLength(LinkList *L)
{
	LinkList *p=L;int i=0;
	while (p->next!=NULL)
	{	i++;
		p=p->next;
	}
	return(i);
}
void DispList(LinkList *L)
{
	LinkList *p=L->next;
	while (p!=NULL)
	{	printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
}
bool GetElem(LinkList *L,int i,ElemType &e)
{
	int j=0;
	LinkList *p=L;
	while (j<i && p!=NULL)
	{	j++;
		p=p->next;
	}
	if (p==NULL)			//不存在第i個數據結點
		return false;
	else					//存在第i個數據結點
	{	e=p->data;
		return true;
	}
}
int LocateElem(LinkList *L,ElemType e)
{
	LinkList *p=L->next;
	int n=1;
	while (p!=NULL && p->data!=e)
	{	p=p->next;
		n++;
	}
	if (p==NULL)
		return(0);
	else
		return(n);
}
bool ListInsert(LinkList *&L,int i,ElemType e)
{
	int j=0;
	LinkList *p=L,*s;
	while (j<i-1 && p!=NULL) //查詢第i-1個結點
	{	j++;
		p=p->next;
	}
	if (p==NULL)	//未找到位序為i-1的結點
		return false;
	else			//找到位序為i-1的結點*p
	{	s=(LinkList *)malloc(sizeof(LinkList));//建立新結點*s
		s->data=e;
		s->next=p->next;						//將*s插入到*p之後
		p->next=s;
		return true;
	}
}
bool ListDelete(LinkList *&L,int i,ElemType &e)
{
	int j=0;
	LinkList *p=L,*q;
	while (j<i-1 && p!=NULL)	//查詢第i-1個結點
	{	j++;
		p=p->next;
	}
	if (p==NULL)				//未找到位序為i-1的結點
		return false;
	else						//找到位序為i-1的結點*p
	{	q=p->next;				//q指向要刪除的結點
		if (q==NULL)
			return false;			//若不存在第i個結點,返回false
		e=q->data;
		p->next=q->next;		//從單鏈表中刪除*q結點
		free(q);				//釋放*q結點
		return true;
	}
}

二:含有主函式的Exam2-6.cpp檔案

#include "linklist.cpp"
void delmaxnode(LinkList *&L)
{
	LinkList *p=L->next,*pre=L,*maxp=p,*maxpre=pre;
	while (p!=NULL)					//用p掃描整個單鏈表,pre始終指向其前驅節點
	{
		if (maxp->data<p->data)		//若找到一個更大的節點
		{	maxp=p;					//更改maxp
			maxpre=pre;				//更改maxpre
		}
		pre=p;						//p、pre同步後移一個節點
		p=p->next;
	}
	maxpre->next=maxp->next;		//刪除*maxp節點
	free(maxp);						//釋放*maxp節點
}
int main()
{
	LinkList *L;
	int n=10;
	ElemType a[]={1,3,2,9,0,4,7,6,5,8};
	CreateListR(L,a,n);
	printf("L:");DispList(L);
	printf("刪除最大值節點\n");
	delmaxnode(L);
	printf("L:");DispList(L);
	DestroyList(L);
	return 0;
}

兩個檔案需要在同一資料夾下,否則需要標示路徑

今天就二級部落格了,surprise,連結串列學會了,看見成長了