最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言實現(xiàn)線性動態(tài)(單向)鏈表的示例代碼

 更新時間:2022年05月16日 10:31:05   作者:非線性光學元件  
本文主要介紹了C語言實現(xiàn)線性動態(tài)(單向)鏈表的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

什么是鏈表

鏈表是數(shù)據(jù)結構里面的一種,線性鏈表是鏈表的一種,線性鏈表的延伸有雙向鏈表和環(huán)形鏈表。在編程語言中優(yōu)化數(shù)據(jù)結構可以在處理大數(shù)據(jù)時大大降低程序的空間復雜性和時間復雜性。這里我只用一個簡單的例子——線性單向鏈表為例,說明C語言是如何實現(xiàn)該結構的。

鏈表的元素是由結構體來實現(xiàn)struct table *p。結構體中有一個成員是結構體指針struct table *next,而這個結構體指針的類型和此結構體類型相同。除鏈表最后一個元素外,每一個結構體的指針都指向鏈表中下一個元素的結構體,最后一個元素的結構體指針為空(NULL)。保存鏈表時,只需要記錄下鏈表的頭指針,即鏈表中第一個結構體的地址即可。添加一個鏈表元素時,都需要單獨申請一段內存;刪除時則將其釋放掉。在查找鏈表時,只需要順著結構體指針的順序一個一個往下查找,直到查找的結構體中的成員指針。以下是一個鏈表結構的示意:

struct Student{
int ID;//學號
char[20];//姓名
int marks[5];//5門考試的成績
struct Student *next;//指向下一個結構體的結構體指針
}

為什么不用結構體數(shù)組

有人會有問為什么不直接用一個結構體數(shù)組代替鏈表,結構體數(shù)組占據(jù)的內存空間是連續(xù)的,如果使用malloc指令一樣可以動態(tài)存儲,而且連續(xù)的內存空間肯定比不確定的內存空間效果要好。但是如果對一個動態(tài)數(shù)組插入或者刪除元素的話,它后面的所有元素都需要變動位置,因此修改數(shù)組會比鏈表要難的多。但它的優(yōu)點在于查找方式很靈活,每一個元素相對于數(shù)組首元素地址都有一個偏移量i,因此對于數(shù)組來說既可以順向查找也可以反向查找,還可以二分法查找。

由于鏈表的每一個元素都有一段內存,這些內存未必是連續(xù)的,加上鏈表本身會比結構體數(shù)組多一個指向下一個元素的結構體指針,因此從節(jié)省內存的角度看鏈表是不如數(shù)組的。但是鏈表刪除元素的時候(假設這個元素是a[k])只需要a[k-1]的next指針指向a[k+1],再把a[k]的內存釋放即可,非常方便;插入元素的時候(假設這個元素是a[n]),只需要a[n-1]的next指針指向a[n]再將a[n]的指針指向a[n+1]即可,相比于數(shù)組來說只修改了兩個元素,速度快而且非常方便。

鏈表的操作

鏈表的操作分為——創(chuàng)建表、插入元素、刪除元素、清空表、查找表、打印表。其中插入/刪除的元素可以是一個也可以說多個。鏈表從存儲類型上來分可以分為靜態(tài)鏈表和動態(tài)鏈表,靜態(tài)鏈表是事先編寫好的鏈表,占用的內存是靜態(tài)存儲區(qū)的內存,使用時不可以對其中的元素進行刪減,只能查找;動態(tài)鏈表是按照程序要求生成的鏈表,存放于動態(tài)存儲區(qū),結構比較靈活,每一個元素都占據(jù)一部分存儲空間,如果要刪除元素,則釋放該位置的內存;如果要添加元素,則申請一個結構體內存區(qū)的內存。

創(chuàng)建表

創(chuàng)建鏈表需要兩個指針,一個作為先行指針(*p1),開辟內存并保存結構體的值;一個作為緩存指針(*p2),保留先行指針的所有值并且將它的next指向先行指針。構建鏈表時,先行指針賦一個值,后行指針保存一個值并且后行指針的next指向先行指針。賦值終止時,先行指針的next指向NULL,同時將先行指針賦值給后行指針,鏈表即構建完畢
代碼窗口可以通過鍵盤的"←"和"→"查看。

struct Student * input()
{
	struct Student *p1,*p2,*head=NULL; 
	printf("************************動態(tài)鏈表實驗***********************\n【輸入動態(tài)鏈表】\n");
	printf("請依次輸入學號	姓名  身高(cm)  體重(kg)(用空格間隔,學號輸入0結束):\n");
	p2=p1=(struct Student *)malloc(LEN);//開辟內存 
	scanf("%d %s %f %f",&p1->ID,&p1->name,&p1->height,&p1->weight);
	if(p1->ID==0)return(head);
	else head=p1;
	while(p1->ID!=0)
	{
		p2->next=p1;
		p2=p1;
		p2->BMI=(float)p2->weight/(p2->height/100)/(p2->height/100);//求BMI指數(shù) 
		p1=(struct Student *)malloc(LEN);//開辟內存 
		scanf("%d %s %f %f",&p1->ID,&p1->name,&p1->height,&p1->weight);
	}
	p2->next=NULL;
	return(head);//返回鏈表頭指針 
}

刪除元素

刪除元素鏈表的第n個元素只需要將第n-1個元素的next指針指向第n+1個元素,再將第n個元素的內存釋放即可,我這里是寫的其中一個例子,根據(jù)關鍵字學號(int stdID)刪除表中的某個元素,同時返回刪除后的鏈表首地址(如果刪的是第一個元素,則鏈表首地址會變)
代碼窗口可以通過鍵盤的"←"和"→"查看。

struct Student *delate(struct Student *head,int stdID)
{
	struct Student *p1,*p2;
	if(head->ID==stdID)
	{
		p1=head->next;
		free(head);
		return p1;
	}//如果刪除的是第一個元素,比較特殊,需要修改頭指針,其余不動
	//剩余幾種情況都是修改next結構體指針 
	for(p1=head;p1!=NULL;p2=p1,p1=p1->next)//p1指針和p2指針同時查找,p1指向當前的學生,p2保指向了上一個學生 
	{
		if(p1->ID==stdID)
		{
		 	p2->next=p1->next;//假設找到了需要刪除的學生的學號,則讓它上一個學生的指針指向跳過他的下一個學生 
		 	free(p1);
		 	return head; 
		}
	}
	return NULL;//返回NULL代表沒找到 
}

插入元素

插入元素的原理是,假設要在第n個元素前插入一個元素。首先判斷它是不是首元素,如果是,則修改頭指針指向該元素,并將該元素的next指向原來的頭指針。如果不是首元素,是第k個元素之前插入一個元素,則將第k-1個元素的next指針指向插入元素(或者子表)的地址(或者頭指針),將插入元素的next指針(或尾指針)指向第k個元素。本示例代碼是根據(jù)一個學號(主要關鍵字)插入一個元素(或者子表)的函數(shù),返回鏈表的首地址(因為如果在第一個元素前面插入,可能改變鏈表的首地址)。
代碼窗口可以通過鍵盤的"←"和"→"查看。

struct Student *insert(struct Student *head,int stdID,struct Student *insertstd)
{
	struct Student *p1,*p2,*p;
	for(p=insertstd;p->next!=NULL;p=p->next);//找到insert鏈表的最后一個元素 
	if(head->ID==stdID)
	{
		p->next=head;
		return insertstd;
	}

	for(p1=head;p1!=NULL;p2=p1,p1=p1->next)
	{
		if(p1->ID==stdID)
		{
			p2->next=insertstd;
			p->next=p1;
			return head; 
		}
	}
	return NULL; 
}

代碼及運行結果

完整代碼及注釋如下:
代碼窗口可以通過鍵盤的"←"和"→"查看。

#include <stdio.h>
#include <malloc.h>
#include <stdbool.h>
#define LEN sizeof(struct Student)//定義結構體變量的大小為符號常量LEN 
struct Student{
	int ID;//學號 
	char name[20];//姓名 
	float height;//身高 
	float weight;//體重
	float BMI;//BMI指數(shù),錄入時不需要計算 
	struct Student *next;//指向下一個結構體 
};
struct Student *input();//輸入函數(shù) 
void output(struct Student * head);//輸出函數(shù) 
struct Student *delate(struct Student *head,int stdID);//刪除一個元素,返回刪除后表的頭指針 
struct Student *insert(struct Student *head,int stdID,struct Student *insertstd);//返回插入元素(子表)后的頭指針 
int append(struct Student *head);//插入一個鏈表,從input函數(shù)輸入 
struct Student *isexist(struct Student *head,int stdID);
int main()
{
	struct Student *present;//當前鏈表的頭指針 
	int choice;
	bool next;
	int stdID;
	/* 
	1:插入一個元素
	2:刪除一個元素
	3:續(xù)表 
	4:查找表 
	*/ 
	printf("**********動態(tài)鏈表實驗**********\n初始化一個鏈表:\n");
	present=input();//當前的鏈表指針
	do{
		printf("請選擇:\n|1:插入元素(子表)\n|2:刪除元素\n|3:續(xù)表\n|4:查找表\n");
		scanf("%d",&choice); 
		switch(choice)	
		{
			case 1:
				printf("請輸入插入地點的后一個同學的學號: ");
				scanf("%d",&stdID);
				if(isexist(present,stdID)==NULL)
				{
					printf("該學生不存在!\n");
					break;//退出switch語句 
				}
				present=insert(present,stdID,input());
				printf("插入元素后的鏈表為:\n");	
				output(present);
				break;
			case 2:
				printf("請輸入刪除元素的學號:  ");
				scanf("%d",&stdID);
				if(isexist(present,stdID)==NULL)
				{
					printf("該學生不存在!\n");
					break;//退出switch語句 
				}
				present=delate(present,stdID);
				printf("刪除后的鏈表為:\n"); 	
				output(present);
				break;
			case 3:
				append(present);
				printf("續(xù)表后的鏈表為:\n");
				output(present);
				break;
			case 4:
				printf("當前鏈表為:\n"); 
				output(present);
				break;
		}
		printf("是否繼續(xù)(Yes:1,No:0):  ");
		scanf("%d",&next);
		fflush(stdin);
	}while(next);

	 
	return 0;	
} 
struct Student * input()
{
	struct Student *p1,*p2,*head=NULL; 
	printf("************************動態(tài)鏈表實驗***********************\n【輸入動態(tài)鏈表】\n");
	printf("請依次輸入學號	姓名  身高(cm)  體重(kg)(用空格間隔,學號輸入0結束):\n");
	p2=p1=(struct Student *)malloc(LEN);//開辟內存 
	scanf("%d %s %f %f",&p1->ID,&p1->name,&p1->height,&p1->weight);
	if(p1->ID==0)return(head);
	else head=p1;
	while(p1->ID!=0)
	{
		p2->next=p1;
		p2=p1;
		p2->BMI=(float)p2->weight/(p2->height/100)/(p2->height/100);//求BMI指數(shù) 
		p1=(struct Student *)malloc(LEN);//開辟內存 
		scanf("%d %s %f %f",&p1->ID,&p1->name,&p1->height,&p1->weight);
	}
	p2->next=NULL;
	return(head);//返回鏈表頭指針 
}
void output(struct Student *head)
{
	struct Student *p;
	int num=1;
	p=head;//將頭指針地址傳給p 
	printf("【輸出動態(tài)鏈表】\n");
	printf("|學號\t\t|姓名\t|身高\t|體重\t|BMI\n");
	while(p!=NULL)
	{
		printf("%3d|%08d\t|%s\t|%5.2f\t|%5.2f\t|%lf\n",num++,p->ID,p->name,p->height,p->weight,p->BMI);
		p=p->next;
	}
}
struct Student *delate(struct Student *head,int stdID)
{
	struct Student *p1,*p2;
	if(head->ID==stdID)
	{
		p1=head->next;
		free(head);
		return p1;
	}//如果刪除的是第一個元素,比較特殊,需要修改頭指針,其余不動
	//剩余幾種情況都是修改next結構體指針 
	for(p1=head;p1!=NULL;p2=p1,p1=p1->next)//p1指針和p2指針同時查找,p1指向當前的學生,p2保指向了上一個學生 
	{
		if(p1->ID==stdID)
		{
		 	p2->next=p1->next;//假設找到了需要刪除的學生的學號,則讓它上一個學生的指針指向跳過他的下一個學生 
		 	free(p1);
		 	return head; 
		}
	}
	return NULL;//返回NULL代表沒找到 
}
struct Student *insert(struct Student *head,int stdID,struct Student *insertstd)
{
	struct Student *p1,*p2,*p;
	for(p=insertstd;p->next!=NULL;p=p->next);//找到insert鏈表的最后一個元素 
	if(head->ID==stdID)
	{
		p->next=head;
		return insertstd;
	}

	for(p1=head;p1!=NULL;p2=p1,p1=p1->next)
	{
		if(p1->ID==stdID)
		{
			p2->next=insertstd;
			p->next=p1;
			return head; 
		}
	}
	return NULL; 
}
int append(struct Student *head)//插入一個鏈表,從input函數(shù)輸入 
{
	struct Student *p;
	for(p=head;p->next!=NULL;p=p->next);//找到head鏈表的最后一個元素 
	p->next=input();//從input輸入需要添加的元素,可以是1個或者多個
	return 0; 
} 
struct Student *isexist(struct Student *head,int stdID)
{
	struct Student *p;
	for(p=head;p!=NULL;p=p->next)
	{
		if(p->ID==stdID)
		{
			return p;
		}
	}
	return NULL;
}

輸出效果如下圖:

C語言輸出動態(tài)鏈表結果1

C語言輸出動態(tài)鏈表結果2

到此這篇關于C語言實現(xiàn)線性動態(tài)(單向)鏈表的示例代碼的文章就介紹到這了,更多相關C語言 線性動態(tài)(單向)鏈表內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • c語言中字符串分割函數(shù)及實現(xiàn)方法

    c語言中字符串分割函數(shù)及實現(xiàn)方法

    下面小編就為大家?guī)硪黄猚語言中字符串分割函數(shù)及實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-05-05
  • Linux中利用c語言刪除某個目錄下的文件

    Linux中利用c語言刪除某個目錄下的文件

    這篇文章主要給大家介紹了Linux中利用c語言刪除某個目錄下文件的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • C++ 如何用cout輸出hex,oct,dec的解決方法

    C++ 如何用cout輸出hex,oct,dec的解決方法

    本篇文章是對C++中如何用cout輸出hex,oct,dec的方法進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C語言實現(xiàn)系統(tǒng)關機注銷功能

    C語言實現(xiàn)系統(tǒng)關機注銷功能

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)系統(tǒng)關機注銷功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • 詳解C語言如何實現(xiàn)雙向帶頭循環(huán)鏈表

    詳解C語言如何實現(xiàn)雙向帶頭循環(huán)鏈表

    雙向帶頭循環(huán)鏈表應該是鏈表中非常方便的一種,可以很容易的在任意位置上進行插入和刪除,可以很容易的對鏈表進行管理。本文將利用C語言實現(xiàn)雙向帶頭循環(huán)鏈表,需要的可以參考一下
    2022-08-08
  • 數(shù)據(jù)結構之位圖(bitmap)詳解

    數(shù)據(jù)結構之位圖(bitmap)詳解

    這篇文章主要介紹了數(shù)據(jù)結構之位圖詳解,本文講解了位圖的基本知識、位圖的實現(xiàn)方法、位圖的應用等內容,需要的朋友可以參考下
    2014-08-08
  • c++制作的時間函數(shù)類

    c++制作的時間函數(shù)類

    本文給大家分享的是一個個人使用C++編寫的時間函數(shù)類,主要是實現(xiàn)了類的定義和調用,相比較來說還算比較復雜的時間類了,推薦給小伙伴們,有需要的朋友可以參考下。
    2015-03-03
  • C指針原理教程之C內嵌匯編

    C指針原理教程之C內嵌匯編

    在學習 C 語言內嵌匯編的實驗過程中,發(fā)現(xiàn)內嵌匯編極容易造成段錯誤。
    2019-02-02
  • 深入剖析Android中init進程實現(xiàn)的C語言源碼

    深入剖析Android中init進程實現(xiàn)的C語言源碼

    這篇文章主要介紹了Android中init進程實現(xiàn)的C語言源碼,init屬性服務在安卓中屬于系統(tǒng)的底層Linux服務,需要的朋友可以參考下
    2015-07-07
  • 詳解C++ 桶排序(BucketSort)

    詳解C++ 桶排序(BucketSort)

    這篇文章主要介紹了C++桶排序,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04

最新評論

绿春县| 略阳县| 卢湾区| 通海县| 贵阳市| 永年县| 大同市| 西藏| 临夏市| 纳雍县| 柞水县| 应城市| 扬中市| 连城县| 定州市| 连南| 永修县| 南丰县| 蓬溪县| 台东县| 江川县| 三门峡市| 报价| 米易县| 镇江市| 囊谦县| 蒙自县| 云霄县| 浏阳市| 五莲县| 松阳县| 和政县| 齐河县| 富源县| 高淳县| 清水河县| 土默特左旗| 东辽县| 儋州市| 永修县| 凤冈县|