目錄
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
好了,今天的分享就到這里兒。別忘了點贊收藏😄😄😄