C语言数据结构学习

动态数组

堆空间示意图
在这里插入图片描述
根据示意图,我们知道如果需要在堆空间开辟三类空间存储数据,一个是管理动态数组的结构体,一个是指针数组本身,一个是每个数组元素本身。如果只是测试,那么数组元素指针对应的数据,可以存在栈空间中,不用开辟堆空间进行存储。

一个文件中实现(C99标准编译)

包含对数组的遍历,增加,删除,查找,扩容

//#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//动态数组的结构体
struct dynamicArray{
	void **pAddr; //维护在堆区真实数组指针
	int m_capacity; //数组容量
	int m_size; //数组元素的个数
};

struct Person{
	char name[64];
	int age;
};

//初始化数组,并返回动态数组的头指针
// 指针函数,返回一个结构体
struct dynamicArray *init_DynamicArray(int capacity){
	if (capacity<=0)
	{
		return NULL;
	}

	struct dynamicArray *array =(struct dynamicArray*)malloc(sizeof(struct dynamicArray));  //指针类型转换

	//判断内存是否申请成功
	if (array==NULL)
	{
		return NULL;
	}

	//设置容量
	array->m_capacity=capacity;
	//设置大小
	array->m_size=0;
	//维护在堆区数组的指针 (在堆空间设置了一个m_capacity大小的空间,让pAddr指向它)
	array->pAddr = (void **)malloc(sizeof(void*)*array->m_capacity);

	return array;

}

//插入功能(void * data :待插入的元素)
void insert_dynamicArray(struct dynamicArray *array,int pos,void * data){
	if (array==NULL)
	{
		return;
	}

	if (data==NULL)
	{
		return;
	}

	if (pos<0 || pos>array->m_size)
	{
		//无效的位置,进行尾插
		pos=array->m_size;
	}

	//先判断是否已经满载,如果满载,动态开辟
	if (array->m_size==array->m_capacity)
	{
		//申请一个更大的空间
		int newCapacity = array->m_capacity*2;

		//创建新的空间
		void ** newSpace =(void **)malloc(sizeof(void*)*newCapacity);

		//将原有的数据拷贝到新的空间下
		memcpy(newSpace,array->pAddr,sizeof(void*)*array->m_capacity);

		//释放原有的空间
		free(array->pAddr);

		//更改指针的指向
		array->pAddr=newSpace;

		//更新容量的大小
		array->m_capacity=newCapacity;

	}

	//插入新的元素
	//从最后一个位置开始,依次移动数据,后移
	//int i;
	for (int i=array->m_size-1;i>=pos;i--)
	{
        array->pAddr[i+1]=array->pAddr[i];
	}

	//将新元素插入到指定的位置
	array->pAddr[pos]=data;

	//更新目前数组的大小
	array->m_size++;
}

//删除数组中的元素
void remove_DynamicArrayById(struct dynamicArray *array,int pos){
    if (array==NULL)
    {
        return;
    }
    
    if (pos<0 || pos > (array->m_size-1))
    {
        //无效的位置,直接return
        return;
    }

    //从pos位置开始,到数组尾部,数据进行前移,逻辑上删除
    for (int i = pos; i < array->m_size-1; i++)
    {
        array->pAddr[i]=array->pAddr[i+1];
    }
    
    array->m_size--;  
}

//删除数组中的元素,通过值
void remove_DynamicArrayByValue(struct dynamicArray *array,void * data,int(*myCompare)(void *,void *)){
     if (array==NULL)
     {
         return;
     }

     if (data==NULL)
     {
         return;
     }

     for (int i = 0; i < array->m_size; i++)
     {
         //(array->pAddr[i])->name==data->name 因为两个指针没法比较,我们需要比较值,就让用户自己传入函数比较
         if (myCompare(array->pAddr[i],data))
         {
            remove_DynamicArrayById(array,i);
            break;
         }
         
     }
         
}

//销毁数组
void destroy_DynamicArray(struct dynamicArray *array){
    if (array==NULL)
    {
       return;
    }

    //先释放数组元素申请的空间
    if (array->pAddr!=NULL)
    {
        free(array->pAddr);
        array->pAddr=NULL;
    }
    
    //释放动态数组
    free(array);
    array=NULL;
      
}

//myCompare函数的实现
int myCompare(void *data1,void *data2){
   struct Person * p1=data1;
   struct Person * p2=data2;

   return strcmp(p1->name,p2->name) == 0 && p1->age == p2->age;  //vs编辑器有时候反应太慢,明明是对的,但是报错
}

//void(*myForeach)(void *) ,指针函数(传入无类型的数据,让用户自己去打印)
void foreach_DynamicArray(struct dynamicArray *array,void(*myForeach)(void *)){
	if (array==NULL)
	{
		return ;
	}

	if(myForeach==NULL){
		return ;
	}
	//int i;
	for (int i=0;i<array->m_size;i++)
	{
		myForeach(array->pAddr[i]); //把数组的首地址传进入,交给用户自己去打印(myForeach属于回调函数)
	}
}



void myPrintPerson(void * data){
	struct Person *p = (struct Person*)data; //感觉像强制类型转换
	printf("姓名:%s 年龄:%d\n",p->name,p->age);
}


void test01(){
    //创建动态数组

	struct dynamicArray *arr = init_DynamicArray(5);

	//准备五个person数据
	struct Person p1={"亚瑟",18};
	struct Person p2={"王昭君",12};
	struct Person p3={"赵云",38};
	struct Person p4={"张飞",19};
	struct Person p5={"关羽",17};
	struct Person p6={"宫本",16};

	//将数据插入到动态数组中
	printf("当前的容量为:%d\n",arr->m_capacity);

	insert_dynamicArray(arr,0,&p1);
	insert_dynamicArray(arr,0,&p2);
	insert_dynamicArray(arr,0,&p3);
	insert_dynamicArray(arr,2,&p4);
	insert_dynamicArray(arr,10,&p5);
	insert_dynamicArray(arr,1,&p6);

	//遍历数组(目前的结果:赵云,宫本,王昭君,张飞,亚瑟,关羽)
	foreach_DynamicArray(arr,myPrintPerson);
	printf("插入后数组的容量为:%d\n",arr->m_capacity);

    //测试,删除index为1处的元素
    printf("删除的后的数组元素:\n");
    remove_DynamicArrayById(arr,1);
    foreach_DynamicArray(arr,myPrintPerson);

    //根据传入的对象,比如,一个结构,张飞删除
    struct Person p={"张飞",19};
    remove_DynamicArrayByValue(arr,&p,myCompare);
    printf("-----------------根据结构体的值删除-------------------\n");
    foreach_DynamicArray(arr,myPrintPerson);
    
    //销毁数组
    destroy_DynamicArray(arr);
    arr=NULL;
    printf("-----------------销毁动态数组-------------------\n");
    foreach_DynamicArray(arr,myPrintPerson);
}


int main(){
	test01();
	system("pause");
	return EXIT_SUCCESS;
}

单向链表

在这里插入图片描述

实现链表的创建,插入,查找(位置与值),删除,清空,销毁

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//链表节点
struct LinkNode{
    void * data; //数据域(可以看作Java中的对象)
    struct LinkNode *next; //指针域
};

//定义节点的数据域
struct Person{
    char name[64];
    int age;
};

//链表结构体
struct LList{
    struct LinkNode pHeader; //头节点
    int m_Size; //链表长度
};

typedef void* LinkList; //将void*定义为LinkList,隐藏指针  (void*应该理解为无类型指针,不能理解为无返回值)

//初始化链表
LinkList init_LinkList(){
    struct LList * myList = malloc(sizeof (struct LList)); //动态开辟一个堆空间存储管理链表得结构体,并用myList指针,指向这个堆空间

    if(myList==NULL){
       return NULL;
    }

    //初始化链表得结构体
    myList->pHeader.data=NULL;
    myList->pHeader.next=NULL;
    myList->m_Size=0;
    return myList;
}

//插入节点,LinkList list=void* ,指的是传入管理链表结构体得指针,pos插入得位置,data待插入得节点
void insert_LinkList(LinkList list,int pos,void* data){

    if(list==NULL){
        return;
    }

    if(data==NULL){
        return;
    }
    struct LList *myList = list;  //由于我们typedef了LinkList为一个无类型指针,需要进行类型转换,、
    if(pos<0 || pos> myList->m_Size){
        //插入得位置不合理,就执行尾插
        pos=myList->m_Size;
    }

    //创建零时节点
    struct LinkNode *pCurrent=&myList->pHeader; //拿到链表的头节点地址
    //通过循环找到插入位置的前驱节点
    for (int i = 0; i < pos; ++i) {
        pCurrent = pCurrent->next;
    }

    //创建出新的节点
    struct LinkNode *newNode = malloc(sizeof(struct LinkNode));
    newNode->data = data;
    newNode->next = NULL;
    //将新节点插入到链表中
    newNode->next=pCurrent->next;
    pCurrent->next=newNode;

    myList->m_Size++; //更新链表长度
}

//删除节点 --按照位置删除
void removeByPos_LinkList(LinkList list,int pos){
    if(list==NULL){
        return;
    }

    struct LList *myList = list;
    if(pos<0 || pos>myList->m_Size-1){
        return;
    }

    //通过一个临时指针来遍历到pos ,先要找到删除节点的前驱节点
    struct LinkNode *pCurrent = &myList->pHeader;
    for (int i = 0; i < pos; ++i) {
        pCurrent=pCurrent->next;
    }

    //删除节点
    //缓存待删除的节点
    struct LinkNode *pDel = pCurrent->next;
    //建立关系
    pCurrent->next=pDel->next;
    free(pDel);
    pDel=NULL;

    myList->m_Size--;
}

int myCompare(void * data1,void * data2){
    struct Person * p1=data1;
    struct Person * p2=data2;
    return strcmp(p1->name,p2->name)==0 && p1->age==p2->age;
}

//删除节点 --按照z值删除
void removeByValue_LinkList(LinkList list,void * data,int(*myCompare)(void *,void *)){
    if(list==NULL){
        return;
    }
    if(data==NULL){
        return;
    }
    struct LList * myList=list;  //还原结构体
    //创建两个赋值指针变量
    struct LinkNode *pPrev = &myList->pHeader;
    struct LinkNode *pCurent = pPrev->next;  // myList->pHeader.next(both ok)
    //先根据比较的内容,找到其内容的前驱节点
    for (int i = 0; i < myList->m_Size-1; ++i) {
        if(myCompare(pCurent->data,data)){
            //更改指针指向
            pPrev->next=pCurent->next;
            //释放掉要删除的节点
            free(pCurent);
            pCurent=NULL;
            break;
        }
        //将两个辅助指针后移
        pPrev=pCurent; //pPrev=pPrev->nex (both ok)
        pCurent=pCurent->next;
    }
    //更新长度
    myList->m_Size--;
}

//清空链表,保留头节点,其余的节点释放掉
void clear_LinkList(LinkList list){
    if(list==NULL){
        return;
    }

    struct LList *myList=list;
    struct LinkNode *pCurrent=myList->pHeader.next;
    for (int i = 0; i < myList->m_Size; ++i) {
        //先要记住下一个节点
        struct LinkNode *pNext=pCurrent->next;
        free(pCurrent);
        pCurrent=pNext;
    }

    myList->pHeader.next=NULL;
    myList->m_Size=0;
}

//销毁一个链表
void destory_LinkList(LinkList list){

    if(list==NULL){
        return;
    }
    //先清空链表
    clear_LinkList(list);
    free(list);
    list=NULL;
}

//遍历节点
void foreach_LinkList(LinkList list,void(*myPrint)(void *)){
    if(list==NULL){
        return;
    }

    struct LList * myList = list;
    struct LinkNode *pCurrnet = myList->pHeader.next; //知道第一个有数据的节点
    //printf("当前的链表长度为:%d\n",myList->m_Size);
    for (int i = 0; i < myList->m_Size; ++i) {
        myPrint(pCurrnet->data);
        pCurrnet=pCurrnet->next;
    }
}

//提供一个接口给用户打印链表的长度
int getSize_LinkList(LinkList list){
    if(list==NULL){
        return -1;
    }

    struct LList *myList=list;
    return myList->m_Size;
}




void myPrintPerson(void * data){
    struct Person * p =data;
    printf("姓名:%s,年龄:%d\n",p->name,p->age);
}
void test01(){
    LinkList list = init_LinkList();
    //struct LList *myList =list;
    //定义几个节点
    //准备五个person数据
    struct Person p1={"亚瑟",18};
    struct Person p2={"王昭君",12};
    struct Person p3={"赵云",38};
    struct Person p4={"张飞",19};
    struct Person p5={"关羽",17};
    struct Person p6={"宫本",16};

    //将数据插入到链表中
//    printf("当前的链表长度为:%d\n",myList->m_Size);

    insert_LinkList(list,0,&p1);
    insert_LinkList(list,0,&p2);
    insert_LinkList(list,1,&p3);
    insert_LinkList(list,0,&p4);
    insert_LinkList(list,1,&p5);
    insert_LinkList(list,100,&p6);

    // 张飞 关羽 王昭君 赵云 亚瑟 宫本
    printf("当前列表的长度:%d\n", getSize_LinkList(list));
    foreach_LinkList(list,myPrintPerson);


    //删除赵云
    removeByPos_LinkList(list,3);
    printf("------------------------\n");
    //张飞 关羽 王昭君  亚瑟 宫本
    printf("当前列表的长度:%d\n", getSize_LinkList(list));
    foreach_LinkList(list,myPrintPerson);


    //删除关羽
    struct Person p={"关羽",17};
    removeByValue_LinkList(list,&p,myCompare);
    printf("------------------------\n");
    //张飞  王昭君  亚瑟 宫本
    printf("当前列表的长度:%d\n", getSize_LinkList(list));
    foreach_LinkList(list,myPrintPerson);

    //清空链表
    clear_LinkList(list);
    printf("------------------------\n");
    printf("当前列表的长度:%d\n", getSize_LinkList(list));
    foreach_LinkList(list,myPrintPerson);

    //销毁链表
    destory_LinkList(list);
}

int main(){


    //测试
    test01();
    system("pause");
    return EXIT_SUCCESS;
}

在这里插入图片描述

企业级链表实现(管理链表的结构体只维护一个指针域,用户流出地址空间用于存储下一个节点地址)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct LinkNode{
    //只有指针域
    struct LinkNode * next;
};

struct Person{
    struct LinkNode next; //这里其实就是利用结构体开辟前四个字节,存储下一个节点的地址
    char name[64];
    int age;
};

//管理链表的结构体
struct LList{
    struct LinkNode pHeader; //链表的头节点
    int m_Size;
};

typedef void* LinkList;
//链表初始化
LinkList init_LinkList(){

    struct LList *myList= malloc(sizeof(struct LList));

    if(myList==NULL){
        return NULL;
    }

    myList->pHeader.next=NULL;
    myList->m_Size=0;

    return myList;
}

//插入节点
void insert_LinkList(LinkList list,int pos,void * data){
    if(list==NULL){
        return;
    }

    if(data==NULL){
        return;
    }

    struct LList *myList=list;
    if(pos<0 || pos> myList->m_Size-1){
        pos = myList->m_Size; //不满足条件就尾插
    }

    //
    struct LinkNode *myNode = data; //data是用户的对象(不只四个字节),但是LinkNode只有指针域(四个字节),系统提取前四个字节自动转换成节点结构体

    //寻找到前置节点位置
    struct LinkNode *pCurrent = &myList->pHeader;
    for (int i = 0; i < pos; ++i) {
        pCurrent = pCurrent->next;
    }

    //交换地址
    myNode->next=pCurrent->next;
    pCurrent->next=myNode;

    //更新链表长度
    myList->m_Size++;

}

//通过传入的位置移除节点
void removeByPos_LinkList(LinkList list,int pos){
    if(list==NULL){
        return;
    }
    struct LList *myList = list;
    if(pos<0 || pos>myList->m_Size-1){
        return;
    }

    struct LinkNode *pCurrent = &myList->pHeader;

    for (int i = 0; i < pos; ++i) {
        pCurrent=pCurrent->next;
    }
    //先缓存下一个节点
    struct LinkNode *pDel =pCurrent->next;
    //更新连接关系
    pCurrent->next=pDel->next;
    //free(pDel);  因为peron的指针域,在栈中,并不需要手动释放堆内存(链表中并没有维护数据域)
    pDel=NULL;

    //节点减一
    myList->m_Size--;

}

//通过传入的值进行删除
void removeByValue_LinkList(LinkList list,void * data,int(*myCompare)(void*,void*)){
    if(list==NULL){
        return;
    }
    if(data==NULL){
        return;
    }

    struct LList *myList = list;
    struct LinkNode *pPrev = &myList->pHeader; //从第一个有数据的点开始
    struct LinkNode *pCurrent = myList->pHeader.next;
    for (int i = 0; i < myList->m_Size; ++i) {
        if(myCompare(pCurrent,data)){ //返回值为1,执行删除操作
            pPrev->next=pCurrent->next;
            pCurrent=NULL;
            break;
        }
        pPrev=pCurrent;
        pCurrent=pCurrent->next;
    }

    myList->m_Size--;

}

int myCompare(void *data1,void *data2){
    struct Person *p1=data1;
    struct Person *p2=data2;
    return strcmp(p1->name,p2->name)==0 && p1->age==p2->age;
}

void destroy_LinkList(LinkList list){
    if(list==NULL){
        return;
    }

    free(list);
    list=NULL;
}

//遍历链表
void foreach_LinkList(LinkList list,void(*myPrintLinkNode)(void *)){
    if(list==NULL){
        return;
    }

    struct LList *myList = list;
    struct LinkNode *pCurrent = myList->pHeader.next;
    for (int i = 0; i < myList->m_Size; ++i) {
        myPrintLinkNode(pCurrent);  //???????
        pCurrent=pCurrent->next;
    }
}



void myPrintLinkNode(void * data){
    struct Person *p =data; //???????????
    printf("姓名:%s 年龄:%d\n",p->name, p->age);
}


void test(){
    LinkList list = init_LinkList();

    struct Person p1={NULL,"aaa",10};
    struct Person p2={NULL,"bbb",11};
    struct Person p3={NULL,"ccc",12};
    struct Person p4={NULL,"ddd",13};
    struct Person p5={NULL,"eee",14};

    insert_LinkList(list,0,&p1);
    insert_LinkList(list,0,&p2);
    insert_LinkList(list,1,&p3);
    insert_LinkList(list,0,&p4);
    insert_LinkList(list,100,&p5);

    //ddd bbb ccc aaa eee
    foreach_LinkList(list,myPrintLinkNode);

    //删除测试
    printf("----------------------------\n");
    removeByPos_LinkList(list,1);
    //ddd  ccc aaa eee
    foreach_LinkList(list,myPrintLinkNode);

    //根据值删除测试
    printf("----------------------------\n");
    struct Person test ={NULL,"aaa",10};
    removeByValue_LinkList(list,&test,myCompare);
    //ddd  ccc  eee
    foreach_LinkList(list,myPrintLinkNode);

    //销毁链表
    printf("----------------------------\n");
    destroy_LinkList(list);
}


int main() {

    test();
    system("pause");
    return EXIT_SUCCESS;
}

在这里插入图片描述

栈 (数组实现)

栈不可以被遍历,因为一旦去遍历栈中所有元素,就会移除栈容器中的所有的元素
遍历算法:属于非质变算法。不重复遗漏访问容器中的所有数据
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1024

//定义栈的结构体
struct SStack{
    void * data[MAX]; //数组
    int m_Size;
};

typedef void* seqStack;
//开始编写stack的接口

//初始化栈
seqStack init_Stack(){

    struct SStack *myStack=malloc(sizeof (struct SStack)); //先给管理栈的结构体开辟空间
    if(myStack==NULL){
        return NULL;
    }

    //清空数组中的每个元素
    memset(myStack->data,0, sizeof(void*)*MAX); //将数组中的每个元素赋值为0

    myStack->m_Size=0;

    return myStack;
}

//入栈
void push_SeqStack(seqStack stack,void * data){
    if(stack==NULL){
        return;
    }

    //判断栈是否已经满了,如果满了,不能入栈
    struct SStack *myStack = stack;
    if(myStack->m_Size==MAX){
        return;
    }

    myStack->data[myStack->m_Size]=data; //入栈插入
    myStack->m_Size++; //更新栈大小
}

//出栈
void pop_SeqStack(seqStack stack){
    if(stack==NULL){
        return ;
    }

    //如果是空栈,不执行出栈
    struct SStack *myStack = stack;
    if(myStack->m_Size==0){
        return ;
    }

//    void *data = myStack->data[myStack->m_Size-1];
//    memset(myStack->data[myStack->m_Size-1],0,sizeof(void *));
    myStack->data[myStack->m_Size-1]=NULL;
    myStack->m_Size--;
}
//获取栈顶元素
void* top_SeqStack(seqStack stack){
    if(stack==NULL){
        return NULL;
    }

    struct SStack *myStack=stack;
    if(myStack->m_Size<=0){
        return NULL;
    }

    return myStack->data[myStack->m_Size-1];
}

//返回栈大小
int size_SeqStack(seqStack stack){
    if(stack==NULL){
        return -1;
    }

    struct SStack *myStack=stack;
    return myStack->m_Size;
}

//判断栈是否为空(0为空,1非空)
int isEmpty(seqStack stack){
    if(stack==NULL){
        return -1; //真
    }

    struct SStack *myStack=stack;
    if(myStack->m_Size<=0){
        return 1; //真
    } else{
        return 0; //假
    }
}

//销毁栈
void destroy_SeqStack(seqStack stack){
    if(stack==NULL){
        return;
    }

    free(stack);
    stack=NULL;
}

//添加数据进行测试
struct Person{
    char name[64];
    int age;
};

void test01(){
    seqStack stack = init_Stack();

    //准备五个person数据
    struct Person p1={"亚瑟",18};
    struct Person p2={"王昭君",12};
    struct Person p3={"赵云",38};
    struct Person p4={"张飞",19};
    struct Person p5={"关羽",17};
    struct Person p6={"宫本",16};

    //全部入栈
    push_SeqStack(stack,&p1);
    push_SeqStack(stack,&p2);
    push_SeqStack(stack,&p3);
    push_SeqStack(stack,&p4);
    push_SeqStack(stack,&p5);

    while (isEmpty(stack)==0){ //如果栈不为空,进行访问栈顶的元素,并且出栈
        struct Person *p = top_SeqStack(stack);
        printf("姓名:%s 年龄:%d\n",p->name,p->age);
        pop_SeqStack(stack);
    }

    //栈的大小
    int size = size_SeqStack(stack);
    printf("当前栈的大小为%d\n",size);

    destroy_SeqStack(stack);
}
int main(){
    test01();
    printf("hello,world! 1");
    return 0;
}

在这里插入图片描述

栈的链式存储实现

#include <stdio.h>
#include <stdlib.h>
//#include <string.h>
//clion智能之处,指针变量指向会变成箭头,结构体才会变成.
//栈节点,只维护指针域
struct stackNode{
    struct stackNode *next;
};

//维护栈的结构体
struct LStack{
    struct stackNode pHeader;
    int m_Size;
};

typedef void* LinkStack;

//初始化栈
LinkStack init_LinkStack(){

    struct LStack *myLinkStack= malloc(sizeof(struct LStack));
    if(myLinkStack==NULL){
        return NULL;
    }

    myLinkStack->pHeader.next=NULL;
    myLinkStack->m_Size=0;
    return myLinkStack;
}

//入栈(插头作为栈顶)
void push_LinkStack(LinkStack stack,void * data){
    if(stack==NULL){
        return;
    }

    if(data==NULL){
        return;
    }

    struct LStack *myStack = stack;
    //先判断是否满栈(链表没有满栈的说法)
//    if(myStack->m_Size){
//
//    }
   struct stackNode *newNode = data;
   newNode->next = myStack->pHeader.next;
   myStack->pHeader.next = newNode;

   myStack->m_Size++;

}

//出栈
void pop_LinkList(LinkStack stack){
    if(stack==NULL){
        return;
    }

    //空栈直接返回
    struct LStack *myStack = stack;
    if(myStack->m_Size<=0){
        return;
    }

    //有元素,做出栈操作
    struct stackNode *temp = myStack->pHeader.next; //临时存储首个有值的节点
    myStack->pHeader.next=temp->next;
    //temp=NULL;

    myStack->m_Size--;
}

//返回栈顶元素
void* top_LinkStack(LinkStack stack){
    if(stack==NULL){
        return NULL;
    }

    struct LStack *myStack = stack;
    if(myStack->m_Size<=0){
        return NULL;
    }

    return myStack->pHeader.next;
}
//返回栈大小
int size_LinkStack(LinkStack stack){
    if(stack==NULL){
        return -1;
    }

    struct LStack *myStack = stack;
    return myStack->m_Size;
}

//判断是否为空(非0是空,0就是非空)
int isEmpty(LinkStack stack){
    if(stack==NULL){
        return -1;
    }
    struct LStack *myStack=stack;
    if(myStack->m_Size<=0){
        return 1;
    }

    return 0;
}

//销毁栈
void destory_LinkStack(LinkStack stack){

    if(stack==NULL){
        return;
    }


    free(stack);
    stack=NULL;

}

struct Person{
    struct stackNode next;
    char name[64];
    int age;
};

void test02(){

    LinkStack  stack = init_LinkStack();

    //准备五个person数据
    struct Person p1={NULL,"亚瑟",18};
    struct Person p2={NULL,"王昭君",12};
    struct Person p3={NULL,"赵云",38};
    struct Person p4={NULL,"张飞",19};
    struct Person p5={NULL,"关羽",17};
    //struct Person p6={NULL,"宫本",16};

    push_LinkStack(stack,&p1);
    push_LinkStack(stack,&p2);
    push_LinkStack(stack,&p3);
    push_LinkStack(stack,&p4);
    push_LinkStack(stack,&p5);



    while (isEmpty(stack)==0){ //如果栈不为空,进行访问栈顶的元素,并且出栈
        struct Person *p = top_LinkStack(stack);
        printf("姓名:%s 年龄:%d\n",p->name,p->age);
        pop_LinkList(stack);
    }



    //栈的大小
    int size = size_LinkStack(stack);
    printf("当前栈的大小为%d\n",size);


    destory_LinkStack(stack);
}

int main(){
    test02();
    printf("hello,world! 2");
    return 0;
}

在这里插入图片描述

clion使用技巧小记

问题:初次使用clion的时候,整个项目中只能存在一个主函数,对于最初的学习并不友好,我们想的是在学习过程中,在一个project中存在多个main函数,并运行之。
其实解决方法很简单,如图
在这里插入图片描述
我们只需要,项目下新建文件夹,将.C源文件创建好后,在同级下新建一个CMakeLists.txt文件,
在txt文件中,添加

include_directories(.)
add_executable(A stackFinishByArray.c )
add_executable(B stackFinishByLinkList.c)

add_executable(),为添加的可以执行的条目,A和B随意起个你知道的名字,作为stackFinishByArray.c和stackFinishByLinkList.c文件的启动名字。这样,stackFinishByArray.c和stackFinishByLinkList.c就都可以包含一个main函数了。
但是同时注意,在第一级的project下有一个系统给我们创建的CMakeLists.txt文件,里面会自动生成如下内容:
在这里插入图片描述
我们需要将系统创建的CMakeLists.txt文件的add_executable()注释掉。
还有,我们的二级目录stackFinishByArray,需要添加到系统生成的
CMakeLists.txt
文件中,即

ADD_SUBDIRECTORY(stackFinishByArray)

这样,就可以在学习阶段,创建并运行多个main函数了,不用学习一个部分再去创建多个project的了。麻烦的很。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值