文章目錄
一、單鏈表與順序表的區別:
二、關于鏈表中的一些函式介面的作用及實作
1、頭檔案里的結構體和函式宣告等等
3.尾插尾刪
4、頭插頭刪
5、單鏈表查找
6、中間插入(在pos后面進行插入)
7、中間洗掉(在pos后面進行洗掉)
8、單獨列印鏈表和從頭到尾列印鏈表
9、test.c
一、單鏈表與順序表的區別:
一、順序表:
1、記憶體中地址連續
2、長度可以實時變化
3、不支持隨機查找
4、適用于訪問大量元素的,而少量需要增添/洗掉的元素的程式
5、中間插入或者洗掉比較方便,記憶體命中率較高
二、鏈表
1、記憶體中地址不連續(邏輯上連續,物理上不連續)
2、長度可以實時變化(避免浪費空間)
3、不支持隨機查找,查找的時間復雜度為o(1),
4、適用于訪問大量元素的,對訪問元素無要求的程式
5、中間插入或者洗掉比較方便,效率高
二、關于鏈表中的一些函式介面的作用及實作
1、創建介面,開辟空間
2、尾插尾刪
3、頭插頭刪
4、查找并修改
5、中插中刪
ps:我看了許多的單鏈表文章,在插刪的介面實作上大多數是往前進行插刪,這里寫的則是往后進行插刪
1、頭檔案里的結構體和函式宣告等等
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SListDataType;
//節點
typedef struct SListNode
{
SListDataType data;
struct SListNode* next;
}SListNode;
//struct SList
//{
// SListNode* head;
// SListNode* tail;
//};
//尾插尾刪
void SListPushBack(SListNode** pphead, SListDataType x);
void SListPopBack(SListNode** pphead);
//頭插頭刪
void SListPushFront(SListNode** pphead, SListDataType x);
void SListPopFront(SListNode** pphaed);
void SListPrint(SListNode* phead);
//查找并修改
SListNode* SListFind(SListNode* phead, SListDataType x);
//中插中刪
void SListInserAfter(SListNode**pphead,SListNode* pos, SListDataType x);
void SListEraseAfter(SListNode* pos);
//從頭到尾列印鏈表
void PrintTailToHead(SListNode* pList);
2、創建介面空間
//開辟的下一個空間
SListNode* BuySListNode(SListDataType x)
{
SListNode* newNode = (SListNode*)malloc(sizeof(SListNode));
if (newNode == NULL)
{
printf("申請結點失敗\n");
exit(-1);
}
newNode->data = x;
newNode->next = NULL;
return newNode;
}
3.尾插尾刪
//尾插
void SListPushBack(SListNode** pphead, SListDataType x)
{
SListNode* newNode = BuySListNode(x);//我們指向頭指標的那個結點是**pphead,*pphead就是頭指標的地址
//如果頭指標的地址為空,我們就把新開辟的這個空間指標(已經傳入值)再賦給頭指標,也就是下面的這個if回圈
if (*pphead == NULL)
{
*pphead = newNode;
}
else
{
//找尾巴,判斷尾巴是不是空地址,這個函式實作的是尾插,我們找到尾巴后,如果尾巴是空地址,我們將插入的newNode賦給尾巴,此時
//實作了尾插,在下面的代碼中,我們首先把頭指標當成尾巴,從頭指標開始依次往后找,如果下一個不是空指標,我們就令
//tail=tail->next,此時指向下一個結點,進入回圈繼續判斷,當找到后,我們再令尾巴=newNode,在上面我們也判斷了頭指標為空的情況
SListNode* tail = *pphead;
while (tail->next!= NULL)
{
tail = tail -> next;
}
tail->next = newNode;
}
}
void SListPopBack(SListNode** pphead)
{
//1、空
//2、一個結點
//3、一個以上
if (*pphead == NULL)
{
return;
}
else if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
SListNode* prev = NULL;
SListNode* tail = *pphead;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
//tail = NULL;//這個無所謂,因為我們釋放后,出了這個作用域,tail和prev都被銷毀,沒人能拿到,所以不會被再找到
prev->next = NULL;
}
}
4、頭插頭刪
//頭插頭刪
void SListPushFront(SListNode** pphead, SListDataType x)
{
SListNode* newnode = BuySListNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
void SListPopFront(SListNode** pphead)
{
//1、空
//2、一個結點+3、一個以上
if (*pphead == NULL)
{
return;
}
//(*phead)->next:*和>都是解參考,同一優先級,我們需要給*pphead帶括號,(*pphead)->next才是下一個結點
else{
//我們頭刪也會遇到情況,我們洗掉第一個的話,第一個里面還存有第二個結點的地址,我們必須在洗掉前,保存第二個結點的地址
SListNode* next = (*pphead)->next;
free(*pphead);//通過除錯我們發現:free前后,*pphead的地址不變,但是*pphead里的值被置為隨機值,free不僅僅把這塊空間還給作業系統
//而且還把這塊空間存的值和地址都置為隨機值
*pphead = next;
}
}
5、單鏈表查找
//單鏈表查找
SListNode* SListFind(SListNode* phead, SListDataType x)
{
SListNode* cur = phead;
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
6、中間插入(在pos后面進行插入)
void SListInserAfter(SListNode** pphead,SListNode* pos, SListDataType x)
{
assert(pos && pphead);
if (*pphead == pos)
{
SListPushFront(pphead, x);
}
else
{
SListNode* newnode = BuySListNode(x);
SListNode* tmp = *pphead;
while (tmp->next != pos)
{
tmp = tmp->next;
}
tmp->next = pos;
pos->next = newnode;
}
}
7、中間洗掉(在pos后面進行洗掉)
void SListEraseAfter(SListNode* pos)
{
//洗掉pos后面的
assert(pos);
if (pos->next)
{
//pos->next=pos->next->next//不推薦
SListNode* next = pos->next;
SListNode* nextnext = next->next;
pos->next = nextnext;
free(next);
}
}
8、單獨列印鏈表和從頭到尾列印鏈表
void SListPrint(SListNode* phead)
{
SListNode* cur = phead;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
void PrintTailToHead(SListNode* pList)
{
if (pList == NULL)
{
return;
}
PrintTailToHead(pList->next);
printf("%d->",pList->data);
}
9、test.c
#include"SList.h"
TestSList1()
{
SListNode* pList = NULL;//這個結構體指標指向開辟的空間,頭指標指向鏈表的開頭
SListPushBack(&pList, 1);
SListPushBack(&pList, 2);
SListPushBack(&pList, 3);
SListPushBack(&pList, 4);
SListPrint(pList);
SListPopBack(&pList);
SListPopBack(&pList);
SListPopBack(&pList);
SListPopBack(&pList);
SListPopBack(&pList);
SListPrint(pList);
SListPushFront(&pList, 1);
SListPushFront(&pList, 2);
SListPushFront(&pList, 6);
SListPushFront(&pList, 4);
SListPushFront(&pList, 5);
SListPrint(pList);
SListPopFront(&pList);
SListPopFront(&pList);
SListPopFront(&pList);
SListPopFront(&pList);
SListPopFront(&pList);
SListPopFront(&pList);
SListPrint(pList);
}
TestSList2()
{
SListNode* pos1;
SListNode* pList = NULL;//這個結構體指標指向開辟的空間,頭指標指向鏈表的開頭
SListPushBack(&pList, 1);
SListPushBack(&pList, 2);
SListPushBack(&pList, 3);
SListPushBack(&pList, 4);
SListPrint(pList);
SListNode* pos = SListFind(pList, 3);
if (pos)
{
pos->data = 30;//這里將cur-data改為pos->data,然后再將pos-data原來的值改為30
}
SListPrint(pList);
pos1 = SListFind(pList, 30);//我們先去找到這個pos1的位置,然后再去插入
SListInserAfter(&pList,pos1,50);//函式傳參要對應起來,我們用指標傳用指標接收,不能在pos1位置直接寫個數字
SListPrint(pList);
SListEraseAfter(pos1);//pList指向第一個結點,pList->next指向第二個結點,那么我們洗掉的是目標節點后面
SListPrint(pList);
//PrintTailToHead(&pList);
}
int main()
{
TestSList1();
TestSList2();
return 0;
}
總結
提示:這里對文章進行總結:
例如:以上就是今天要講的內容,本文僅僅簡單介紹了pandas的使用,而pandas提供了大量能使我們快速便捷地處理資料的函式和方法,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/297842.html
標籤:python
