單鏈表的實現 | 附學生信息管理系統的實現

目錄

1.前言:

2.單鏈表的相關概念:

2.1定義:

2.2形式:

2.3特點:

3.常見功能及代碼?:

3.1創建節點:

3.2頭插:

3.3尾插:

3.4頭刪:

3.5尾刪:

3.6插入(指定位置pos之前)

3.7插入(在指定位置pos之后)

3.8刪除(指定位置pos前)

3.9刪除(指定位置pos之后)

3.10打印鏈表:

3.11查找

3.12銷毀鏈表:

4.總代碼:

4.1 SList.h

4.2 SList.c

4.3 test.c

5.附:學生信息管理與信息系統:

6.總結:


1.前言:

今天,小鄧兒帶咱們來看看一個常見的數據結構——“單鏈表”。通過今天的學習,你將熟練地掌握單鏈表,還可以將其應用在學生信息管理系統中。廢話不多說,咱們開始今天的探秘。

2.單鏈表的相關概念:

2.1定義:

單鏈表(Singly Linked List)是一種鏈式存儲的線性數據結構,由一系列節點(Node)組成,每個節點包含兩個部分:

  • 數據域(Data):存儲實際的數據元素。
  • 指針域(Next):存儲指向下一個節點的引用(或指針)。

2.2形式:

以整型數據為例:

2.3特點

  • 節點通過指針依次連接,形成鏈狀結構。
  • 最后一個節點的指針域為?null(或?None),表示鏈表的結束。
  • 鏈表的大小是動態的,可以靈活地插入和刪除節點。

3.常見功能及代碼?:

3.1創建節點:

3.2頭插:

思路:

1.定義一個新節點newnode;

2.newnode的下一個結點指向頭節點;

3.將newnode作為新的頭節點。

代碼:

3.3尾插:

思路:

1.判斷該鏈表是否為空。若是空鏈表,同頭插思路相同;

2.若是不為空。遍歷鏈表,將最后一個節點的下一個節點,指向新節點。

代碼:

3.4頭刪:

思路:

1.判空。若為空,返回NULL;

2.不為空,定義一個next指針(指向頭節點下一個節點);

3.將next作為新的頭節點。

代碼:

3.5尾刪:

思路:

1.判空。若為空,返回NULL;

2.不為空,定義一個pre指針指向NULL,再定義一個ptail指針遍歷鏈表;

3.當ptail的下一個節點不為空,將pre指向ptail所在位置,ptail繼續遍歷鏈表,直至ptail下一個指針為空;

4.此時,將pre的下一個指針指為空,并釋放ptail指針空間。

代碼:

3.6插入(指定位置pos之前)

思路:

1.判空。若為空,調用頭插;

2.不為空,定義一個新節點newnode來存儲要插入的數據;

3.在定義一個pre指針指向頭節點(用來尋找*pos);

4.找到pos后,將pre的下一個節點指向newnode節點,并將newnode的下一個節點指向pos;

代碼:

3.7插入(在指定位置pos之后)

思路:

1.判空。若為空,調用頭插;

2.不為空,定義一個新節點newnode來存儲要插入的數據;

3.將newnode的下一個節點指向pos的下一個節點;

4.再將pos的下一個節點指向newnode.(注意:這里的3、4步驟不可以顛倒

正常思路:

如果顛倒:(newnode的下一個節點,就不能指向原先4所在的節點。只能指向newnode節點)

代碼:

3.8刪除(指定位置pos前)

思路:

1.判斷pos是否為頭節點,是的話,頭刪;

2.不是頭節點,定義一個pcur節點指向頭節點;

3.用pcur來遍歷鏈表,直至pcur的下一個節點是pos;

4.此時,將pcur的下一個節點指向pos的下一個節點,并釋放pos節點的空間。

代碼:

3.9刪除(指定位置pos之后)

思路:

1.判斷pos是否為頭節點,是的話,頭刪;

2.不是頭節點,定義一個pcur節點指向pos的下一個節點;

3.將pos的下一個節點指向pcur的下一個節點。

代碼:

3.10打印鏈表:

代碼:

3.11查找:

代碼:

3.12銷毀鏈表:

代碼:

4.總代碼:

4.1 SList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLDateType;
typedef struct SLNode
{SLDateType data;struct Node* next;
}Node;
Node* BuyNode(SLDateType X);
//打印
void SLPrintf(Node*plist);
//尾插
void SLPushBack(Node** plist, SLDateType X);
//頭插
void SLPushFront(Node** plist, SLDateType X);
//尾刪
void SLPopback(Node** plist);
//頭刪
void SLPopFront(Node** plist);
//查找
Node* SLSearch(Node* plist, SLDateType X);
//指定位置前插入
void SLInsert(Node** plist, Node*pos,SLDateType X);
//指定位置之后插入
void SLInsertAfter(Node** plist, Node* pos, SLDateType X);
//刪除指定位置的數據
void SLErase(Node** plist, Node* pos);
//刪除指定節點后的數據
void SLEraseAfter( Node**plist,Node* pos);
//銷毀
void SLDestory(Node** plist);

4.2 SList.c

#include"SList.h"
Node* BuyNode(SLDateType X)
{Node* newnode = (Node*)malloc(sizeof(SLDateType));if (newnode == NULL){perror("malloc fail\n");return NULL;}newnode->data = X;newnode->next = NULL;return newnode;
}
void SLPrintf(Node* plist)
{if(plist==NULL){exit(1);}Node* pcur = plist;while (pcur){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}
void SLPushBack(Node** phead, SLDateType X)
{assert(phead);Node* newnode = BuyNode(X);if (*phead == NULL){*phead = newnode;}else{Node* ptail = *phead;while (ptail->next){ptail = ptail->next;}ptail->next = newnode;}
}
void SLPushFront(Node** phead, SLDateType X)
{assert(phead);Node* newnode = BuyNode(X);newnode->next = *phead;*phead = newnode;
}
void SLPopback(Node** plist)
{assert(plist&&*plist);if ((plist && *plist) == NULL){free(*plist);*plist= NULL;}else{Node* pre = NULL;Node* ptail =* plist;while (ptail->next){pre = ptail;ptail = ptail->next;}pre->next = NULL;free(ptail);ptail = NULL;}
}
void SLPopFront(Node** plist)
{assert(plist && *plist);if ((plist && *plist) == NULL){free(*plist);*plist = NULL;}else{Node*next=(*plist)->next;free(*plist);*plist = next;}
}
Node* SLSearch(Node* plist, SLDateType X)
{assert(plist);Node* pcur = plist;while (pcur->data != X){pcur = pcur->next;}if (pcur->next){return pcur;}else return NULL;
}
void SLInsert(Node**plist,Node*pos, SLDateType X)
{assert(plist && pos);if (pos == plist){SLPushFront;}else{Node* newnode=BuyNode(X);Node* pre = *plist;while (pre->next != pos){pre = pre->next;}pre->next = newnode;newnode->next= pos;}
}
void SLInsertAfter(Node** plist, Node* pos, SLDateType X)
{assert(plist && pos);if (pos == plist){SLPushFront;}else{Node* newnode = BuyNode(X);newnode->next = pos->next;pos->next = newnode;}
}
void SLErase(Node** plist, Node* pos)
{assert(plist && pos);if (pos == *plist){SLPopFront(&plist);}else {Node* pcur = *plist;while((pcur->next) != pos){pcur = pcur->next;}pcur->next = pos->next;free(pos);pos = NULL;}
}
void SLEraseAfter(Node**plist, Node* pos)
{assert( pos);Node* pcur = pos->next;pos->next = pcur->next;free(pcur);pcur = NULL;
}
void SLDestory(Node** plist)
{Node* pcur = *plist;while (pcur){Node* pre = pcur->next;free(pcur);pcur = pre;}*plist = NULL;
}

4.3 test.c

#include"SList.h"
void test1()
{Node* p1 = (Node*)malloc(sizeof(Node));Node* p2 = (Node*)malloc(sizeof(Node));Node* p3 = (Node*)malloc(sizeof(Node));assert(p1&&p2&&p3);if (p1 == NULL){return 0;}p1->data = 1;p2->data = 2;p3->data = 3;p1->next = p2;p2->next = p3;p3->next = NULL;Node* plist = p1;SLPrintf(plist);
}
void test2()
{Node* plist = NULL;SLPushBack(&plist, 1);SLPushBack(&plist, 2);SLPushBack(&plist, 3);SLPushBack(&plist, 4);//SLPrintf(plist);SLPushFront(&plist, 5);SLPrintf(plist);SLPopback(&plist);SLPrintf(plist);SLPopFront(&plist);SLPrintf(plist);Node* P = SLSearch(plist, 2);if (P){printf("找到%d了\n", P->data);}else printf("未找到\n");SLInsert(&plist, P, 6);//SLPrintf(plist);SLInsertAfter(&plist, P, 7);SLPrintf(plist);SLErase(&plist, P);SLPrintf(plist);SLEraseAfter(&plist,7);SLPrintf(plist);SLDestory(plist);
}int main()
{test2();return 0;
}

5.附:學生信息管理與信息系統:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>typedef struct Student {char id[10];char name[20];float score;
} Stu;typedef struct LinkNode {Stu* data;struct LinkNode* next;
} Node;// 初始化單鏈表
void InitList(Node** L) {*L = (Node*)malloc(sizeof(Node));if (*L == NULL) {perror("malloc failed!\n");exit(1);}(*L)->next = NULL;(*L)->data = NULL;
}// 創建新結點
Node* CreateNode(Stu* x) {Node* newNode = (Node*)malloc(sizeof(Node));if (newNode == NULL) {perror("malloc failed!\n");exit(1);}newNode->data = x;newNode->next = NULL;return newNode;
}// 插入記錄(尾插)
void Insert(Node** L, Stu* x) {Node* newNode = CreateNode(x);if (*L == NULL) {*L = newNode;}else {Node* ptail = *L;while (ptail->next) {ptail = ptail->next;}ptail->next = newNode;}
}// 查找功能1:按姓名查找
Node* SearchByName(Node* L, char* name) {Node* pcur = L->next;while (pcur) {if (strcmp(pcur->data->name, name) == 0) {return pcur;}pcur = pcur->next;}return NULL;
}// 查找功能2:按學號查找
Node* SearchByID(Node* L, char* id) {Node* pcur = L->next;while (pcur) {if (strcmp(pcur->data->id, id) == 0) {return pcur;}pcur = pcur->next;}return NULL;
}// 刪除功能:按學號刪除記錄
void Delete(Node** L, char* id) {Node* c = SearchByID(*L, id);if (c == NULL) {printf("未找到學號為 %s 的記錄!\n", id);return;}Node* pre = *L;while (pre->next != c) {pre = pre->next;}pre->next = c->next;free(c->data);free(c);printf("刪除成功!\n");
}// 修改功能:按學號修改記錄
void Change(Node** L, char* id) {Node* c = SearchByID(*L, id);if (c == NULL) {printf("未找到學號為 %s 的記錄!\n", id);return;}Stu* s = (Stu*)malloc(sizeof(Stu));if (s == NULL) {perror("malloc failed!\n");exit(1);}printf("請輸入修改后的信息(學號 姓名 成績):\n");scanf("%s%s%f", s->id, s->name, &s->score);strcpy(c->data->id, s->id);strcpy(c->data->name, s->name);c->data->score = s->score;free(s);printf("修改成功!\n");
}// 輸出所有記錄
void DispList(Node* L) {Node* pcur = L->next;if (!pcur) {printf("鏈表為空,無記錄可顯示!\n");return;}printf("所有記錄如下:\n");while (pcur) {printf("學號:%s,姓名:%s,成績:%.2f\n",pcur->data->id, pcur->data->name, pcur->data->score);pcur = pcur->next;}
}// 銷毀鏈表
void Destroy(Node** L) {Node* pcur = *L;while (pcur) {Node* temp = pcur;pcur = pcur->next;free(temp->data);free(temp);}*L = NULL;
}// 顯示菜單
void show_screen() {printf("\n***************       功能選擇     *****************\n");printf("*************** 1: 錄入學生記錄     ***************\n");printf("*************** 2: 添加學生記錄     ***************\n");printf("*************** 3: 按學號刪除記錄   ***************\n");printf("*************** 4: 按學號修改記錄   ***************\n");printf("*************** 5: 按姓名查找記錄   ***************\n");printf("*************** 6: 顯示所有記錄     ***************\n");printf("*************** 7: 清屏             ***************\n");printf("*************** 8: 退出管理系統     ***************\n");
}int main() {Node* LinkStudent = NULL;InitList(&LinkStudent);while (1) {int choose;show_screen();printf("請選擇:\n");scanf("%d", &choose);int c;while ((c = getchar()) != '\n' && c != EOF); // 清空scanf緩沖區switch (choose) {case 1: // 添加學生信息printf("請輸入學生信息(學號 姓名 成績),輸入三次:\n");for (int i = 0; i < 3; i++) {Stu* s = (Stu*)malloc(sizeof(Stu));if (s == NULL) {perror("malloc failed!\n");exit(1);}scanf("%s%s%f", s->id, s->name, &s->score);Insert(&LinkStudent, s);}break;case 2: // 添加單條學生記錄{Stu* s = (Stu*)malloc(sizeof(Stu));if (s == NULL) {perror("malloc failed!\n");exit(1);}printf("請輸入學生信息(學號 姓名 成績):\n");scanf("%s%s%f", s->id, s->name, &s->score);Insert(&LinkStudent, s);}break;case 3: // 按學號刪除記錄{char id[10];printf("請輸入要刪除的學號:");scanf("%s", id);Delete(&LinkStudent, id);}break;case 4: // 按學號修改記錄{char id[10];printf("請輸入要修改的學號:");scanf("%s", id);Change(&LinkStudent, id);}break;case 5: // 按姓名查找記錄{char name[20];printf("請輸入要查找的姓名:");scanf("%s", name);Node* result = SearchByName(LinkStudent, name);if (result) {printf("找到記錄:學號:%s,姓名:%s,成績:%.2f\n",result->data->id, result->data->name, result->data->score);}else {printf("未找到姓名為 %s 的記錄!\n", name);}}break;case 6: // 顯示所有記錄DispList(LinkStudent);break;case 7: // 清屏system("cls");break;case 8: // 退出管理系統Destroy(&LinkStudent);printf("退出系統,拜拜!\n");return 0;default: // 輸入錯誤printf("無效選項,請重新輸入!\n");break;}}return 0;
}

6.總結:

小鄧兒的本次學生信息管理系統,在插入、刪除部分只用了一種方式,不是很完善,咱們可以用自行思考,看看怎么樣加入其他方式,使得系統選擇更多O(∩_∩)O

好了,今天的分享就到這里兒。別忘了點贊收藏😄😄😄

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/75782.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/75782.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/75782.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java實用工具類Localstorage

public class LocalStorageUtil {//提供ThreadLocal對象,private static ThreadLocal threadLocalnew ThreadLocal();public static Object get(){return threadLocal.get();}public static void set(Object o){threadLocal.set(o);}public static void remove(){threadLocal.r…

LLM-大語言模型淺談

目錄 核心定義 典型代表 核心原理 用途 優勢與局限 未來發展方向 LLM&#xff08;Large Language Model&#xff09;大語言模型&#xff0c;指通過海量文本數據訓練 能夠理解和生成人類語言的深度學習模型。 核心定義 一種基于深度神經網絡&#xff08;如Transformer架…

【小兔鮮】day03 Home模塊與一級分類

【小兔鮮】day03 Home模塊與一級分類 1. Home-整體結構搭建和分類實現1.1 頁面結構 2. Home-banner輪播圖功能實現 1. Home-整體結構搭建和分類實現 1.1 頁面結構 分類實現 2. Home-banner輪播圖功能實現 輪播圖實現 在HomeBanner.vue中寫出輪播圖的結構 在apis目錄下新建h…

C++中的多態和模板

#include <iostream> #include <cstdlib> #include <ctime> #include <string>using namespace std;// 武器基類 class Weapon { public:virtual ~Weapon() {}virtual string getName() const 0; // 獲取武器名稱virtual int getAtk() const 0; …

Spring 概念

Spring 是一個功能強大、靈活且廣泛使用的 Java 企業級開發框架&#xff0c;它誕生于 2003 年&#xff0c;由 Rod Johnson 創建&#xff0c;初衷是簡化 Java EE 的開發過程。 一、Spring 是什么&#xff1f; 簡單來說&#xff1a; Spring 是一個輕量級的 Java 開發框架&#…

神經網絡之損失函數

引言&#xff1a;損失函數 &#xff08;Loss Function&#xff09;是機器學習和深度學習中非常重要的一個概念。用于衡量模型的預測值與真實值之間的差異&#xff0c;從而指導模型優化其參數以最小化這種差異。 一、損失函數作用 量化誤差&#xff1a;損失函數是將預測值和真實…

Java 基礎-32-枚舉-枚舉的應用場景

在Java編程中&#xff0c;枚舉&#xff08;Enum&#xff09;提供了一種強大的方式來定義一組固定的常量。它們不僅限于簡單的用途&#xff0c;還可以包含構造函數、方法和字段等高級功能&#xff0c;使其適用于多種不同的應用場景。本文將探討幾種常見的使用枚舉的場景&#xf…

【網絡安全】安全的網絡設計

網絡設計是網絡安全的基礎&#xff0c;一個好的網絡設計可以有效的防止攻擊者的入侵。在本篇文章中&#xff0c;我們將詳細介紹如何設計一個安全的網絡&#xff0c;包括網絡架構&#xff0c;網絡設備&#xff0c;網絡策略&#xff0c;以及如何處理網絡安全事件。 一、網絡架構…

網絡安全-等級保護(等保) 0. 前言

各位伙伴好&#xff1a; 招投標總結已過去一年了&#xff0c;時間飛逝&#xff0c;一直忙于工作&#xff0c;等保相關的內容斷斷續續整理了近半年的時間&#xff0c;但一直無暇完成博客內容。 等保已經是一個成熟的體系&#xff0c;現在已進入等保2.0時代&#xff0c;相關政策…

TLS協議詳解

TLS協議 一&#xff0c;TLS協議的組成 TLS協議架構模塊分為兩層&#xff1a;TLS記錄協議&#xff0c;TLS握手協議 ① TLS記錄協議&#xff1a; 是所有子協議的基層&#xff0c;規定了TLS收發數據的基本單位。所有子協議都需要通過記錄協議發出&#xff0c;多個記錄數據可以在…

ollama更新升級及警告解決

1. 概述 在大模型業務處理中&#xff0c;需要用到gemma3 和 qwen2.5-VL&#xff0c;當前服務器的ollama版本 0.3.11&#xff0c;無法滿足要求&#xff0c;需要更新升級。 2. 實施過程 參考官網升級要求&#xff1a; curl -fsSL https://ollama.com/install.sh | sh 不知道…

ubuntu 配置固定ip

在裝服務器系統的時候&#xff0c;DHCP自動獲取ip時&#xff0c;路由可能會重新分配ip&#xff0c;為避免產生影響&#xff0c;可以關閉DHCP將主機設置為靜態ip。 系統環境 Ubuntu 22.04-Desktop 配置方式 一、如果是裝的Ubuntu圖形化&#xff08;就是可以用鼠標操作點擊應用…

套接字編程函數recv和send ,以及設置reuseaddress

recv就是去套接字讀緩沖區讀數據 阻塞模式下&#xff1a;讀緩沖區沒數據那就阻塞等待&#xff0c;若等待被打斷返回-1設置errno為EINTR 非阻塞模式下&#xff1a;讀緩沖區沒數據那就返回-1&#xff0c;設置errno為EAGAIN或EWOULDBLOCK。 若連接斷開返回0&#xff0c;讀取成功…

《C++后端開發最全面試題-從入門到Offer》目錄

當今科技行業對C++開發者的需求持續高漲,從金融科技到游戲開發,從嵌入式系統到高性能計算,C++憑借其卓越的性能和靈活性始終占據著關鍵地位。然而,成為一名優秀的C++工程師并非易事,不僅需要扎實的語言基礎,還要掌握現代C++特性、設計模式、性能優化技巧以及各種工業級開…

設計模式簡述(十)責任鏈模式

責任鏈模式 描述基本使用使用 描述 如果一個請求要經過多個類似或相關處理器的處理。 可以考慮將這些處理器添加到一個鏈上&#xff0c;讓請求逐個經過這些處理器進行處理。 通常&#xff0c;在一個業務場景下會對整個責任鏈進行初始化&#xff0c;確定這個鏈上有哪些Handler…

初識數據結構——Java集合框架解析:List與ArrayList的完美結合

&#x1f4da; Java集合框架解析&#xff1a;List與ArrayList的完美結合 &#x1f31f; 前言&#xff1a;為什么我們需要List和ArrayList&#xff1f; 在日常開發中&#xff0c;我們經常需要處理一組數據。想象一下&#xff0c;如果你要管理一個班級的學生名單&#xff0c;或…

ReFormX:現代化的 React 表單解決方案 - 深度解析與最佳實踐

ReFormX文檔 表單開發一直是前端工作中最繁瑣卻又最常見的任務之一。從簡單的登錄表單到復雜的多步驟配置頁面&#xff0c;開發者往往需要編寫大量重復代碼&#xff0c;處理繁瑣的狀態管理、數據驗證和聯動邏輯。ReFormX 應運而生&#xff0c;它不僅是一個表單組件庫&#xff…

WinForm真入門(9)——RichTextBox控件詳解

WinForm中RichTextBox控件詳解&#xff1a;從基礎到高級應用 上一文中筆者重點介紹了TextBox控件的詳細用法&#xff0c;忘記的 請點擊WinForm真入門(8)——TextBox控件詳解&#xff0c;那么本文中的RichTextBox與TextBox有什么區別嗎&#xff0c;光看名字的話&#xff0c;多了…

Draw.io 全面解析與競品分析:圖表繪制工具的深度對比

目錄 一、Draw.io 全面介紹 1. 產品概述 2. 核心功能特點 3. 用戶體驗 4. 商業模式 二、市場競品分析 1. 主要競品概覽 2. 深度功能對比 3. 價格策略對比 4. 技術架構對比 三、用戶場景與選擇建議 1. 不同場景下的工具推薦 2. 未來發展趨勢 四、結論 diagrams.net…

kafka分區策略詳解

Kafka 分區策略詳解 Kafka 的分區策略決定了消息在生產者端如何分配到不同分區&#xff0c;以及在消費者端如何動態分配分區以實現負載均衡。以下是 Kafka 核心分區策略及其適用場景的詳細解析&#xff1a; 1、生產者分區策略 生產者負責將消息發送到 Topic 的特定分區&#…