C-數據結構-鏈式存儲棧(二次封裝)

/*
二次封裝 借用已經實現雙向鏈表結構來實現
棧 出棧入棧操作類似于 從頭節點開始的插入和刪除
*/

llist.h

#ifndef LLIST_H__
#define LLSIT_H__
#define LLIST_FORWARD	1
#definr LLIST_BACKWARD	2
typedef void llist_op(const void *);//回調函數
typedef int llist_cmp(const void *,const void *);struct llist_node_st
{struct llist_node_st *prev;struct llist_node_st *next;	char data[0];
};
typedef struct
{int size;struct llist_node_st head;
}LLSIT;LLIST *llist_create(int initsize);
int llist_insert(LLIST *,const void *data,int mode);void *llist_find(LLIST *, const void *key, llist_cmp *);//數據類型不統一使用void 百搭
int llist_delete(LLIST *,const void *key,llist_cmp *);
int llist_fetch(LLIST *,const void *key,llist_cmp *,void *data);void llist_travel(LLIST *,llist_op *);
void llist_destroy(LLIST *);#endif

llist.c

#include<stdio.h>
#include<stdlib.h>
#include"llist.h"
#include<string.h>LLIST *llist_create(int initsize)//只包含一個頭節點( 雙向循環鏈表)
{LLIST *new;new = malloc(sizeof(*new));if(new == NULL)return NULL;new->size= initsize;new->head.prev = new->head;new->head.next = new->head;return new;
}
int llist_insert(LLIST *ptr,const void *data,int mode)
{struct llist_node_st *newnode;newnode = malloc(sizeof(*newnode)+ptr->size);if(newnode == NULL)return -1;//newdata->data = malloc(ptr->size);memcpy(newnode->data,data,ptr->size);if(mode == LLIST_FORWARD){newnode->prev = &ptr->head;newnode->next = ptr->head.next;newnode->prev->next = newnode;//頭節點的 next 指針設置為指向新節點 newnodenewnode->next->prev = newnode;//原本在頭節點之后的節點的 prev 指針設置為指向新節點 newnode。}else if(mode == LLIST_BACKWARD){newnode->prev = ptr->head.prev;newnode->next = &ptr->head;newnode->prev->next = newnode;newnode->next->prev = newnode;}else{return -3;}return 0;
}
static struct list_node_st * find_(LLIST *ptr, const void *key, llist_cmp *cmp)
{struct llist_node_st *cur;for(cur = ptr->head.next;cur!=ptr.head;cur=cur->next){if(cmp(key,cur->data) == 0)break;}return cur;
}void *llist_find(LLIST *ptr, const void *key, llist_cmp *cmp)
{struct llist_node_st *node;node = find_(ptr,key,cmp);if(node == &ptr->head))return NULL;return node->data;
}
int llist_delete(LLIST *ptr,const void *key,llist_cmp *cmp)
{	struct llist_node_st *node;node = nodefind_(ptr,key,cmp);if(node == &ptr->head)return -1;node->prev->next = node->next;node->next->prev = node->prev;free(node);return 0;
}
int llist_fetch(LLIST *ptr,const void *key,llist_cmp *cmp,void *data)
{struct llist_node_st *node;node = nodefind_(ptr,key,cmp);if(node == &ptr->head)return -1;node->prev->next = node->next;node->next->prev = node->prev;if(data!=NULL)memcpy(data,node->data,ptr->size);free(node);return 0;
}
void llist_travel(LLIST *ptr,llist_op *op)//需要一個回調函數,需要用戶給我傳一個函數
{struct llist_node_st *cur;for(cur = ptr->head.next;cur!=&ptr->head;cur=cur->next)//為了封裝成更通用的函數,不知道用戶的結構類型,因此需要回調函數,且需要在 .h文件中使用 void 函數聲明,且使用typedef重命名 看起來更好一些op(cur->data);//借用戶之手,把他知道的數據類型打印了出來  具有通用性}
void llist_destroy(LLIST *ptr)
{struct llist node_st *cur,*next;for(cur= ptr->head.next;cur != &ptr->head;cur= next){next = cur->next;free(cur);}free(ptr);
}

stack.h

#ifndef STACK_H__
#define STACK_H__
#include"llish.h"typedef LLIST STACK;
STACK *stack_create(int);
int stack_push(STACK *,const void data);
int stack_pop(STACK *, void *data);void stack_destory(STACK *);#endif

stack.c

#include<stdio.h>
#include<stdlib.h>#include"stack.h"STACK *stack_create(int initsize)
{return llist_create(initsize);
}int stack_push(STACK *ptr,const void data)
{return llist_insert(ptr,data,LLIST_FORWARD);
}static int alaways_match(const void *p1,const void *p2)
{return 0;
}int stack_pop(STACK *ptr, void *data)
{return  llist_fetch(ptr,(void *)0,always_match,data);//(void *)0
}void stack_destory(STACK *ptr)
{llist_destory(ptr);
}

main.c


#include<stdio.h>
#include<stdlib.h>
#include"stack.h"//此時不要包含llish.h 底層庫與二次封裝庫的區別
#define NAMESIZE	32
struct score_st
{int id;char name[NAMESIZE];int math;int chinese;
};
static void print_s(void *record)
{struct score_st *r = record;printf("%d %s %d %d\n",r->id,r->name,r->math,r->chinese);
}
int main()
{STACK *st;int i,ret;struct score_st tmp;st = stack_create(sizeof(struct score_st));if(st ==NULL)exit(1);for(i =0;i<7;i++){tmp.id = i;snprintf(tmp.name,NAMESIZE,"stu%d",i);tmp.math = rand()%100;tmp.chinese = rand()%100;if(stack_push(st,&tmp))exit(1);}while(){ret = stack_pop(st,&tmp);if(ret == -1)break;print_s(&tmp);}stack_destory(st);exit(0);
}

Makefile

all:stack
stack:stack.o main.o llist.o$(CC) $^ -o $@
clean:rm stack *.o -rf

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

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

相關文章

分組排序取最大sql理解

分組排序取最大sql理解 --用戶過濾&#xff08;只能看到當前用戶對應部門用戶權限表中的部門&#xff09; select h.pk_tbdept from jygyl_bmyhqxb h left join jygyl_bmyhqxb_b b on h.pk_bmyhqx b.pk_bmyhqx where isnull(h.dr,0) 0 and isnull(b.dr,0) 0 and b.pk…

類圖的六大關系

類圖中的六大關系包括&#xff1a;繼承關系、實現關系、關聯關系、聚合關系、組合關系和依賴關系。 1. 繼承關系 繼承是一種類與類之間的關系&#xff0c;表示一種泛化和特化的關系。子類繼承父類的特性和行為。 class Animal {void eat() {System.out.println("This an…

TensorFlow.js

什么是 TensorFlow.js&#xff1f; TensorFlow.js 是一個基于 JavaScript 的機器學習庫&#xff0c;它是 Google 開發的 TensorFlow 的 JavaScript 版本。它使得開發者能夠在瀏覽器中直接運行機器學習模型&#xff0c;而不需要依賴于后端服務器或云服務。TensorFlow.js 的主要…

【JavaEE 初階(十)】JVM

?博主主頁: 33的博客? ??文章專欄分類:JavaEE?? &#x1f69a;我的代碼倉庫: 33的代碼倉庫&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;關注我帶你了解更多進階知識 目錄 1.前言2.JVM內存區域劃分3.類加載3.1雙親委派模型 4.垃圾回收&#xff08;GC&#xff0…

【智能優化算法】粒子群優化算法(PSO)【附python實現代碼】

寫在前面&#xff1a; 首先感謝兄弟們的訂閱&#xff0c;讓我有創作的動力&#xff0c;在創作過程我會盡最大能力&#xff0c;保證作品的質量&#xff0c;如果有問題&#xff0c;可以私信我&#xff0c;讓我們攜手共進&#xff0c;共創輝煌。 路雖遠&#xff0c;行則將至&#…

【軟件設計師】下午題總結-數據流圖、數據庫、統一建模語言

下午題總結 1 試題一1.1 結構化語言 2 試題二弱實體增加權限增加實體間聯系和聯系的類型 3 試題三3.1 UML關系例子 3.2 例子&#xff08;2016上半年&#xff09;3.3 設計類分類3.3.1 接口類3.3.2 控制類3.3.3 實體類 3.4 簡答題3.4.1 簡要說明選擇候選類的原則3.4.2 某個類必須…

Kafka SSL認證

證書生成 在kafka安裝目錄下/certificates生成keystore和trust文件&#xff0c;在其中一臺機器聲生成證書&#xff0c;然后將 生成的server.keystore.jks和server.truststore.jks文件拷貝其他broker節點上去即可 1.生成keystore [rootm1 certificates]# keytool -keystore se…

Mantine UI:簡潔、靈活的 React UI 庫

介紹 Mantine UI Mantine UI 是一個由 React 驅動的現代 UI 庫&#xff0c;旨在簡化開發人員構建用戶界面的過程。它提供了一系列經過優化和可訪問的組件&#xff0c;適用于各種項目&#xff0c;從簡單的網站到復雜的應用程序。Mantine UI 的特點包括&#xff1a; 可定制性&a…

Android-okhttp調接口傳參簡單舉例

步驟1&#xff1a;在主線程中創建thread調接口 new Thread(new Runnable() {Overridepublic void run() {getServiceList();}}).start();步驟2&#xff1a;okhttp調接口 private void getServiceList(){Message msg new Message();try{OkHttpClient okHttpClient new OkHttp…

【網絡安全】網絡安全協議的重要性

一.網絡安全 1.什么是網絡安全 網絡安全&#xff08;Cyber Security&#xff09;是指網絡系統的硬件、軟件及其系統中的數據受到保護&#xff0c;不因偶然的或者惡意的原因而遭受到破壞、更改、泄露&#xff0c;系統連續可靠正常地運行&#xff0c;網絡服務不中斷。 2.網絡安…

WPF密碼輸入框明文掩碼切換

1&#xff0c;效果 2&#xff0c;代碼&#xff1a; WPF的PasswordBox不能像Winform中的PasswordBox那樣&#xff0c;通過PasswordBox.PasswordChar(char)0顯示明文。所以這里使用無外觀控件構筑掩碼明文切換。 無外觀控件遵守Themes/Generic.xaml文件配置. <ResourceDicti…

視覺檢測實戰項目——九點標定

本文介紹九點標定方法 已知 9 個點的圖像坐標和對應的機械坐標,直接計算轉換矩陣,核心原理即最小二乘擬合 {??′=????+????+????′=??′??+??′??+??′ [??1??11??2??21?????9??91][????′????′????′]=[??1′??…

[Linux]磁盤管理

一.Linux磁盤管理的原理 磁盤分區與Linux的目錄是借助"掛載機制"鏈接的&#xff0c;將一個分區與一個目錄連接起來。訪問目錄&#xff0c;相當于訪問某塊分區 lsblk命令: lsblk命令可以查看磁盤分區&#xff0c;以及每個分區所掛載的目錄 lsblk -f 可以查看更細節的…

山東大學軟件學院項目實訓-創新實訓-基于大模型的旅游平臺(十九)- JUC(5)

synchronized優化原理 輕量級鎖 如果一個對象有多個線程訪問&#xff0c;但多線程訪問的時間是錯開的&#xff08;沒有競爭&#xff09;&#xff0c;可以用輕量級鎖優化 Slf4j(topic "c.ExerciseTransfer")public class Test {?static final Object obj new Obj…

關于陽光雨露外派聯想的面試感想

最近在找工作&#xff0c;接到了一個陽光雨露外派聯想的面試邀請。說實在的一開始就有不對勁的感覺。想必這就是大廠的自信吧&#xff0c;上就問能不能現場面試&#xff0c;然后直接發面試邀請。這時候我倒是沒覺得有啥問題。 然后今天就去面試去了&#xff0c;住的比較偏&…

【研發日記】【策劃向】(一)游戲策劃其實就是一道加減法題

文章目錄 序設計的過程其實是控制自己欲望的過程我海納百川&#xff0c;你要不要看看&#xff1f;我跟別人不一樣&#xff01;我的人設就是沒有人設&#xff0c;或者說任何人設都是我的人設 記 序 不知不覺進入這個行業幾年了&#xff0c;也經歷了獨立開發和團隊開發的過程。在…

欣賞倪詩韻青桐斷紋古琴很罕見:萬中無一。

欣賞倪詩韻青桐斷紋古琴很罕見&#xff1a;萬中無一。龍池側簽海門倪詩韻制&#xff0c;帶收藏證書此琴斷紋優美如江面波光粼粼&#xff0c;為流水蛇腹斷&#xff0c;是倪老師作品精品中的精品。細心的朋友可以看出倪老師在這張琴上題字非常小心認真。用一個詞來形容——萬中無…

CPython3.7.9源碼學習一:C語言基礎、整數對象

C 語言基礎 結構體 // struct(關鍵字) 名稱 {結構體成員};// 定義結構體 struct Student { char name[50]; int age; float score; };// 初始化 結構體變量 struct Student stu1; strcpy(stu1.name, "張三"); stu1.age 20; stu1.score 90.5;// 初始化 …

Spring Boot線程池的 使用

一.異步方法 1.啟動類加EnableAsync注解 2.在需要異步執行的方法上添加Async注解 3.直接調用 結論&#xff1a;異步方法是通過SpringBoot中自動注入的線程池任務執行器實現的 二.自定義線程池 1.創建線程的配置類 2.使用Async注解時指定名稱 3.結論 手動注入多個線程池任務執…

Java 18新特性

Java 18引入了一系列新的特性和改進&#xff0c;這些更新覆蓋了從基本語言構造到更高級別的API等多個方面。以下是一些Java 18的主要新特性&#xff1a; 模式匹配增強&#xff1a;Java 18改進了模式匹配功能&#xff0c;使其更加強大和易于使用。開發人員可以使用模式匹配來簡…