数据结构笔记

动态数组实现

数据的初始化、指定位置插入、头部删除、尾部删除、指定位置删除。

头文件:

#pragma once

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

struct DynamicArray{
    void **data; //数据空间首地址
    int capacity;//容量,当前数据空间最大能够容纳多少个元素
    int size; //大小,当前数据空间有多少元素
};

#ifdef __cplusplus
extern "C"{
#endif

    typedef int(compare)(void*, void*);

    //初始化函数
    void *Init_DynamicArray();
    //指定位置插入
    int Insert_DynamicArray(void *arr, int pos, void *data);
    //头部插入
    int PushFront_DynamicArray(void *arr, void *data);
    //尾部插入
    int PushBack_DynamicArray(void *arr, void *data);
    //指定位置删除
    int RemoveByPos_DynamicArray(void *arr, int pos);
    //根据值来删除
    int RemoveByVal_DynamicArray(void *arr, void *data, compare *mycompare);
    //头部删除
    int PopFront_DynamicArray(void *arr);
    //尾部删除
    int PopBack_DynamicArray(void *arr);
    //获得数组大小
    int Size_DynamicArray(void *arr);
    //获得容量
    int Capacity_DynamicArray(void *arr);
    //打印函数
    void Foreach_DynamicArray(void *arr,void(*foreach)(void *));
    //销毁数组
    int Destroy_DynamicArray(void *arr);


#ifdef __cplusplus
}
#endif

 

头文件实现:

#include"DynamicArray.h"

//初始化函数
void *Init_DynamicArray(){

    struct DynamicArray *arr = malloc(sizeof(struct DynamicArray));
    if (NULL == arr){
        return NULL;
    }

    arr->capacity = 10; //默认数组创建,容量是10
    arr->data = malloc(sizeof(void *)* arr->capacity);
    arr->size = 0;


    return arr;
}
//指定位置插入
int Insert_DynamicArray(void *arr, int pos, void *data){

    if (NULL == arr){
        return -1;
    }

    if (NULL == data){
        return -2;
    }

    struct DynamicArray *myarr = (struct DynamicArray *)arr;

    if (pos < 0 || pos > myarr->size){
        pos = myarr->size;
    }

    //判断空间是否足够
    if (myarr->size == myarr->capacity){
        
        //根据增长策略,计算新空间大小
        int newcapacity = myarr->size * 2;
        //开辟新空间
        void **newspace = (void **)malloc(sizeof(void *)* newcapacity);
        //将旧空间的数据拷贝到新空间
        memcpy(newspace, myarr->data, sizeof(void *)* myarr->capacity);
        //释放旧空间内存
        free(myarr->data);
        //更新数组核心数据
        myarr->data = newspace;
        myarr->capacity = newcapacity;
    }

    //将元素插入到新空间
    for (int i = myarr->size - 1; i >= pos;i --){
        myarr->data[i + 1] = myarr->data[i];
    }

    //元素插入到pos位置
    myarr->data[pos] = data;

    //维护size大小
    myarr->size++;

    return 0;
}
//头部插入
int PushFront_DynamicArray(void *arr, void *data){
    return Insert_DynamicArray(arr, 0 , data);
}
//尾部插入
int PushBack_DynamicArray(void *arr, void *data){
    struct DynamicArray *myarr = (struct DynamicArray *)arr;
    return Insert_DynamicArray(arr, myarr->size, data);
}
//指定位置删除
int RemoveByPos_DynamicArray(void *arr, int pos){
    
    if (NULL == arr){
        return -1;
    }

    struct DynamicArray *myarr = (struct DynamicArray *)arr;
    if (myarr->size == 0){
        return 0;
    }

    if (pos < 0 || pos > myarr->size - 1){
        return 0;
    }

    for (int i = pos; i < myarr->size - 1; i ++){
        myarr->data[i] = myarr->data[i + 1];
    }

    myarr->size--;

    return 0;
}
//根据值来删除
int RemoveByVal_DynamicArray(void *arr, void *data, compare *mycompare){

    if (NULL == arr){
        return -1;
    }

    if (NULL == data){
        return -2;
    }

    if (NULL == mycompare){
        return -3;
    }

    struct DynamicArray *myarr = (struct DynamicArray *)arr;
    if (myarr->size == 0){
        return 0;
    }

    for (int i = 0; i < myarr->size - 1;i ++){
        
        if (mycompare(myarr->data[i], data)){
            //说明找到了
            RemoveByPos_DynamicArray(arr, i);
            break;
        }
    }


    return 0;
}
//头部删除
int PopFront_DynamicArray(void *arr){
    return RemoveByPos_DynamicArray(arr, 0);
}
//尾部删除
int PopBack_DynamicArray(void *arr){
    struct DynamicArray *myarr = (struct DynamicArray *)arr;
    return RemoveByPos_DynamicArray(arr, myarr->size - 1);
}
//获得数组大小
int Size_DynamicArray(void *arr){
    struct DynamicArray *myarr = (struct DynamicArray *)arr;
    return myarr->size;
}
//获得容量
int Capacity_DynamicArray(void *arr){
    struct DynamicArray *myarr = (struct DynamicArray *)arr;
    return myarr->capacity;
}

//打印函数
void Foreach_DynamicArray(void *arr, void(*foreach)(void *)){
    if (NULL == arr){
        return;
    }

    if (NULL == foreach){
        return;
    }

    struct DynamicArray *myarr = (struct DynamicArray *)arr;

    for (int i = 0; i < myarr->size; i++){
        foreach(myarr->data[i]);
    }
}

//销毁数组
int Destroy_DynamicArray(void *arr){

    if (NULL == arr){
        return -1;
    }

    struct DynamicArray *myarr = (struct DynamicArray *)arr;

    if (myarr->data != NULL){
        myarr->capacity = 0;
        myarr->size = 0;
        free(myarr->data);
        myarr->data = NULL;
    }

    free(myarr);
    myarr = NULL;


    return 0;
}

测试文件:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"DynamicArray.h"

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

void myPrint(void *data){
    struct Person *person = (struct Person *)data;
    printf("Name:%s Age:%d\n",person->name,person->age);
}

int myComapre(void *d1, void *d2){
    struct Person *p1 = (struct Person *)d1;
    struct Person *p2 = (struct Person *)d2;

    return (strcmp(p1->name, p2->name) == 0) && p1->age == p2->age;
}

void test(){

    struct Person p1 = { "aaa", 10 };
    struct Person p2 = { "bbb", 20 };
    struct Person p3 = { "ccc", 30 };
    struct Person p4 = { "ddd", 40 };
    struct Person p5 = { "eee", 50 };
    struct Person p6 = { "fff", 60 };
    struct Person p7 = { "ggg", 70 };
    struct Person p8 = { "hhh", 80 };
    struct Person p9 = { "iii", 90 };
    struct Person p10 = { "jjj", 100 };
    struct Person p11 = { "kkk", 110 };

    //初始化数组
    void *myarray = Init_DynamicArray();
    //插入元素
    Insert_DynamicArray(myarray, 0, &p1);
    Insert_DynamicArray(myarray, 0, &p2);
    Insert_DynamicArray(myarray, 0, &p3);
    Insert_DynamicArray(myarray, 0, &p4);
    Insert_DynamicArray(myarray, 0, &p5);
    Insert_DynamicArray(myarray, 100, &p6);
    printf("Capacity:%d\n", Capacity_DynamicArray(myarray));
    PushFront_DynamicArray(myarray, &p7);
    PushFront_DynamicArray(myarray,  &p8);
    PushFront_DynamicArray(myarray,  &p9);

    PushBack_DynamicArray(myarray, &p10);
    PushBack_DynamicArray(myarray, &p11);

    //遍历 //9 8 7 5 4 3  2 1 6  10 11
    Foreach_DynamicArray(myarray, myPrint);
    printf("Capacity:%d\n",Capacity_DynamicArray(myarray));
    printf("Size:%d\n", Size_DynamicArray(myarray));

    printf("--------头删和尾删之后-------------\n");
    //删除
    PopFront_DynamicArray(myarray);
    PopBack_DynamicArray(myarray);
    Foreach_DynamicArray(myarray, myPrint);
    printf("--------删除2位置之后-------------\n");
    RemoveByPos_DynamicArray(myarray, 2);
    Foreach_DynamicArray(myarray, myPrint);
    printf("--------删除age = 10 name = aaa位置之后-------------\n");

    struct Person pDel = { "aaa", 10 };

    RemoveByVal_DynamicArray(myarray, &pDel, myComapre);
    Foreach_DynamicArray(myarray, myPrint);

    //销毁
    Destroy_DynamicArray(myarray);

}

int main(){

    test();

    system("pause");
    return EXIT_SUCCESS;
}

 

队列

一种先进先出的数据结构,一端插入一端删除。

存储方式:分为顺序队列、链式队列

 

队列顺序存储:

头文件:

#pragma once


#include<stdlib.h>

//顺序队列
struct SQueue{
    void *data[1024]; //保存数据的内存
    int size;
};

typedef void *SeqQueue;

#ifdef __cplusplus
extern "C"{
#endif

    //初始化
    SeqQueue Init_SeqQueue();
    //入队
    void Push_SeqQueue(SeqQueue queue, void *data);
    //出队
    void Pop_SeqQueue(SeqQueue queue);
    //获得队头元素
    void *Front_SeqQueue(SeqQueue queue);
    //获得队尾元素
    void *Back_SeqQueue(SeqQueue queue);
    //获得队列大小
    int Size_SeqQueue(SeqQueue queue);
    //销毁队列
    void Destroy_SeqQueue(SeqQueue queue);

#ifdef __cplusplus
}
#endif

 

头文件实现:

#include"SeqQueue.h"


//初始化
SeqQueue Init_SeqQueue(){

    struct SQueue *queue = malloc(sizeof(struct SQueue));
    if (NULL == queue){
        return NULL;
    }
    queue->size = 0;
    for (int i = 0; i < 1024; i ++){
        queue->data[i] = NULL;
    }

    return queue;
}
//入队
void Push_SeqQueue(SeqQueue queue, void *data){

    if (NULL == queue){
        return;
    }

    if (NULL == data){
        return;
    }

    struct SQueue *q = (struct SQueue *)queue;

    if (q->size == 1024){
        return;
    }


    //移动元素,把0号位置空出来
    for (int i = q->size - 1; i >= 0; i--){
        q->data[i + 1] = q->data[i];
    }

    q->data[0] = data;
    q->size++;

}
//出队
void Pop_SeqQueue(SeqQueue queue){
    if (NULL == queue){
        return;
    }

    struct SQueue *q = (struct SQueue *)queue;
    if (q->size == 0){
        return;
    }
    q->size--;

}
//获得队头元素
void *Front_SeqQueue(SeqQueue queue){
    if (NULL == queue){
        return NULL;
    }

    struct SQueue *q = (struct SQueue *)queue;
    return q->data[q->size - 1];
}
//获得队尾元素
void *Back_SeqQueue(SeqQueue queue){
    if (NULL == queue){
        return NULL;
    }

    struct SQueue *q = (struct SQueue *)queue;
    return q->data[0];
}
//获得队列大小
int Size_SeqQueue(SeqQueue queue){
    if (NULL == queue){
        return -1;
    }

    struct SQueue *q = (struct SQueue *)queue;
    return q->size;
}
//销毁队列
void Destroy_SeqQueue(SeqQueue queue){
    if (NULL == queue){
        return;
    }
    free(queue);
    queue = NULL;
}

 

 

测试文件:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"SeqQueue.h"

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

void test(){

    //创建数据
    struct Person p1 = { "aaa", 10 };
    struct Person p2 = { "bbb", 20 };
    struct Person p3 = { "ccc", 30 };
    struct Person p4 = { "ddd", 40 };
    struct Person p5 = { "eee", 50 };

    //初始化队列
    SeqQueue queue = Init_SeqQueue();
    //数据入队列
    Push_SeqQueue(queue, &p1);
    Push_SeqQueue(queue, &p2);
    Push_SeqQueue(queue, &p3);
    Push_SeqQueue(queue, &p4);
    Push_SeqQueue(queue, &p5);

    //输出队头 队尾元素
    struct Person *front =  (struct Person *)Front_SeqQueue(queue);
    struct Person *back = (struct Person *)Back_SeqQueue(queue);
    printf("队头元素: Name:%s Age:%d\n",front->name,front->age);
    printf("队尾元素: Name:%s Age:%d\n", back->name, back->age);
    printf("-----------------------------\n");

    //输出队列中元素
    while (Size_SeqQueue(queue) > 0){
        //获得对头元素
        front = (struct Person *)Front_SeqQueue(queue);
        printf("Name:%s Age:%d\n", front->name, front->age);
        //弹出队头元素
        Pop_SeqQueue(queue);
    }

    //打印大小
    printf("Size:%d\n",Size_SeqQueue(queue));

    //销毁队列
    Destroy_SeqQueue(queue);

}

int main(){

    test();

    system("pause");
    return EXIT_SUCCESS;
}

 

队列的链式存储:

 

头文件:

#pragma once

#include"LinkList.h"

struct QueueNode{
	struct LinkNode node;
};

#ifdef __cplusplus
extern "C"{
#endif

	//初始化链式队列
	void *Init_LinkQueue();
	//入队列
	void Push_LinkQueue(void *queue, void *data);
	//出队
	void Pop_LinkQueue(void *queue);
	//大小
	int Size_LinkQueue(void *queue);
	//获得队头元素
	void *Front_LinkQueue(void *queue);
	//获得队尾元素
	void *Back_LinkQueue(void *queue);
	//销毁队列
	void Destroy_LinkQueue(void *queue);


#ifdef __cplusplus
}
#endif

 

#pragma once

#include<stdlib.h>

//链表小节点

//目的 : 第一,让用户数据包含 第二,我需要把用户指针类型转换成struct LinkNode*类型
struct LinkNode{
    struct LinkNode *next;
};

//链表结构体
struct LList{
    struct LinkNode header;
    int size;
};

typedef void *LinkList;

//初始化
LinkList Init_LinkList();

//指定位置插入
void Insert_LinkList(LinkList list, int pos, struct LinkNode *data);
//位置删除
void RemoveByPos_LinkList(LinkList list, int pos);
//遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *));
//根据位置获得值
void *Get_LinkList(LinkList list,int pos);
int Size_LinkList(LinkList list);


//销毁
void Destroy_LinkList(LinkList list);

 

 

 

头文件实现:

#include"LinkQueue.h"

//初始化链式队列
void *Init_LinkQueue(){
    return Init_LinkList();
}
//入队列
void Push_LinkQueue(void *queue, void *data){
    Insert_LinkList(queue, 0, data);
}
//出队
void Pop_LinkQueue(void *queue){
    RemoveByPos_LinkList(queue, Size_LinkList(queue) - 1);
}
//大小
int Size_LinkQueue(void *queue){
    return Size_LinkList(queue);
}
//获得队头元素
void *Front_LinkQueue(void *queue){
    return Get_LinkList(queue , Size_LinkList(queue) - 1);
}
//获得队尾元素
void *Back_LinkQueue(void *queue){
    return Get_LinkList(queue, 0);
}
//销毁队列
void Destroy_LinkQueue(void *queue){
    Destroy_LinkList(queue);
}
#include"LinkList.h"


//初始化
LinkList Init_LinkList(){

    struct LList *list = malloc(sizeof(struct LList));
    if (NULL == list){
        return NULL;
    }
    list->header.next = NULL;
    list->size = 0;

    return list;
}
//指定位置插入
void Insert_LinkList(LinkList list, int pos, struct LinkNode *data){
    
    if (NULL == list){
        return;
    }

    if (NULL == data){
        return;
    }
    
    struct LList *llist = (struct LList *)list;

    if (pos < 0 || pos >llist->size){
        pos = llist->size;
    }

    //查找pos位置前一个位置的节点
    struct LinkNode *pCurrent = &(llist->header);
    for (int i = 0; i < pos;i ++){
        pCurrent = pCurrent->next;
    }

    //将新节点插入到链表
    data->next = pCurrent->next;
    pCurrent->next = data;

    llist->size++;
}

//位置删除
void RemoveByPos_LinkList(LinkList list, int pos){

    if (NULL ==list){
        return;
    }

    struct LList *llist = (struct LList *)list;


    if (llist->size == 0){
        return;
    }

    if (pos < 0 || pos > llist->size - 1){
        return;
    }


    //找到pos位置的前一个节点
    struct LinkNode *pCurrent = &(llist->header);
    for (int i = 0; i < pos; i ++){
        pCurrent = pCurrent->next;
    }

    //缓存下待删除节点
    struct LinkNode *pDel = pCurrent->next;
    //重新建立待删除的节点前驱后继节点关系
    pCurrent->next = pDel->next;

    llist->size--;
}


//根据位置获得值
void *Get_LinkList(LinkList list, int pos){
    if (NULL == list){
        return NULL;
    }

    struct LList *llist = (struct LList *)list;
    if (pos < 0 || pos > llist->size - 1){
        return NULL;
    }

    //辅助指针变量
    struct LinkNode *pCurrent = &(llist->header);
    for (int i = 0; i < pos; i++){
        pCurrent = pCurrent->next;
    }


    return pCurrent->next;
}

int Size_LinkList(LinkList list){
    if (NULL == list){
        return -1;
    }

    struct LList *llist = (struct LList *)list;
    return llist->size;
}


//遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *)){
    if (NULL == list){
        return;
    }

    struct LList *llist = (struct LList *)list;
    //辅助指针变量
    struct LinkNode *pCurrent = llist->header.next;
    while (pCurrent != NULL){
        foreach(pCurrent);
        pCurrent = pCurrent->next;
    }
}

//销毁
void Destroy_LinkList(LinkList list){
    if (NULL == list){
        return;
    }

    free(list);
    list = NULL;
}

 

测试代码:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"LinkQueue.h"

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

void test(){

    //创建测试数据
    struct Person p1 = { NULL ,"aaa", 10 };
    struct Person p2 = { NULL ,"bbb", 20 };
    struct Person p3 = { NULL ,"ccc", 30 };
    struct Person p4 = { NULL ,"ddd", 40 };
    struct Person p5 = { NULL ,"eee", 50 };
    
    void *queue = Init_LinkQueue();

    //数据入队
    Push_LinkQueue(queue, &p1);
    Push_LinkQueue(queue, &p2);
    Push_LinkQueue(queue, &p3);
    Push_LinkQueue(queue, &p4);
    Push_LinkQueue(queue, &p5);

    struct Person *front = (struct Person *)Front_LinkQueue(queue);
    struct Person *back = (struct Person *)Back_LinkQueue(queue);
    printf("Front: Name:%s Age:%d\n",front->name,front->age);
    printf("Back: Name:%s Age:%d\n", back->name, back->age);
    printf("-------------------------------\n");
    //输出队列中的元素
    while (Size_LinkQueue(queue) > 0){
        
        front = (struct Person *)Front_LinkQueue(queue);
        printf("Name:%s Age:%d\n", front->name, front->age);
        //弹出队头元素
        Pop_LinkQueue(queue);
    }

    //销毁队列
    Destroy_LinkQueue(queue);

}

int main(){

    test();

    system("pause");
    return EXIT_SUCCESS;
}

 

数据先进后出,以高地址为栈顶。存储方式分为链式存储和顺序存储

 

顺序存储栈的容器:

顺序栈的头文件:

#pragma once

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

#define MAX 1024

//顺序栈
struct SeqStack{
    void *data[MAX];
    int size;
};

#ifdef __cplusplus
extern "C"{
#endif

    //初始化栈
    void *Init_SeqStack();
    //入栈
    void Push_SeqStack(void *stack, void *data);
    //出栈
    void Pop_SeqStack(void *stack);
    //获得大小
    int Size_SeqStack(void *stack);
    //获得栈顶元素
    void *Top_SeqStack(void *stack);
    //销毁栈
    void Destroy_SeqStack(void *stack);


#ifdef __cplusplus
}
#endif

 

顺序栈头文件的实现:

#include"SeqStack.h"

//初始化栈
void *Init_SeqStack(){
    struct SeqStack *stack = malloc(sizeof(struct SeqStack));
    stack->size = 0; 
    for (int i = 0; i < MAX; i ++){
        stack->data[i] = 0;
    }

    return stack;
}
//入栈
void Push_SeqStack(void *stack, void *data){
    if (0 == stack){
        return;
    }
    if (0 == data){
        return;
    }
    struct SeqStack *s = (struct SeqStack *)stack;
    s->data[s->size] = data;
    s->size++;
}
//出栈
void Pop_SeqStack(void *stack){

    if (0 == stack){
        return;
    }
    struct SeqStack *s = (struct SeqStack *)stack;
    s->size--;
}
//获得大小
int Size_SeqStack(void *stack){
    if (0 == stack){
        return -1;
    }
    struct SeqStack *s = (struct SeqStack *)stack;
    return s->size;
}
//获得栈顶元素
void *Top_SeqStack(void *stack){
    if (0 == stack){
        return NULL;
    }
    struct SeqStack *s = (struct SeqStack *)stack;
    return s->data[s->size - 1];
}
//销毁栈
void Destroy_SeqStack(void *stack){
    if (0 == stack){
        return;
    }
    free(stack);
}

 

测试文件:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"SeqStack.h"

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

void test(){

    //测试数据
    struct Person p1 = { "aaa", 10 };
    struct Person p2 = { "bbb", 20 };
    struct Person p3 = { "ccc", 30 };
    struct Person p4 = { "ddd", 40 };
    struct Person p5 = { "eee", 50 };
    //初始化栈
    void *stack = Init_SeqStack();
    //数据入栈
    Push_SeqStack(stack, &p1);
    Push_SeqStack(stack, &p2);
    Push_SeqStack(stack, &p3);
    Push_SeqStack(stack, &p4);
    Push_SeqStack(stack, &p5);
    //输出栈中所有元素
    while (Size_SeqStack(stack) > 0){
        
        //获得栈顶元素
        struct Person * person = (struct Person *)Top_SeqStack(stack);
        //输出栈顶元素
        printf("Name:%s Age:%d\n",person->name,person->age);
        //弹出栈顶元素
        Pop_SeqStack(stack);

    }

    //销毁栈
    Destroy_SeqStack(stack);
}

int main(){

    test();

    system("pause");
    return EXIT_SUCCESS;
}

 

 

链式栈的实现:

链式栈的头文件:

#pragma once

#include<stdlib.h>

struct LinkNode{
    struct LinkNode *next;
};

//链式栈
struct LStack{
    struct LinkNode header;
    int size;
};

typedef void* LinkStack;
#ifdef __cplusplus
extern "C"{
#endif

    //初始化
    LinkStack Init_LinkStack();
    //入栈
    void Push_LinkStack(LinkStack stack, void *data);
    //出栈
    void Pop_LinkStack(LinkStack stack);
    //获得栈顶元素
    void *Top_LinkStack(LinkStack stack);
    //大小
    int Size_LinkStack(LinkStack stack);
    //销毁栈
    void Destroy_LinkStack(LinkStack stack);

#ifdef __cplusplus
}
#endif

 

头文件的实现:

#include"LinkStack.h"

//初始化
LinkStack Init_LinkStack(){
    struct LStack *stack = (struct LStack *)malloc(sizeof(struct LStack));
    stack->header.next = NULL;
    stack->size = 0;

    return stack;
}
//入栈
void Push_LinkStack(LinkStack stack, void *data){

    if (NULL == stack){
        return;
    }

    if (data == NULL){
        return;
    }

    struct LStack *s = (struct LStack *)stack;
    struct LinkNode *d = (struct LinkNode *)data;

    d->next =  s->header.next;
    s->header.next = d;

    s->size++;

}
//出栈
void Pop_LinkStack(LinkStack stack){
    if (NULL == stack){
        return;
    }
    struct LStack *s = (struct LStack *)stack;
    if (s->size == 0){
        return;
    }

    //缓存下待删除节点
    struct LinkNode *pDel = s->header.next;
    s->header.next = pDel->next;

    s->size--;
}
//获得栈顶元素
void *Top_LinkStack(LinkStack stack){
    if (NULL == stack){
        return NULL;
    }

    struct LStack *s = (struct LStack *)stack;

    return s->header.next;
}
//大小
int Size_LinkStack(LinkStack stack){
    if (NULL == stack){
        return -1;
    }

    struct LStack *s = (struct LStack *)stack;
    return s->size;
}
//销毁栈
void Destroy_LinkStack(LinkStack stack){

    if (NULL == stack){
        return;
    }

    free(stack);
    stack = NULL;
}

 

测试文件:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"LinkStack.h"

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

void test(){
    
    //创建数据
    struct Person p1 = { NULL, "aaa", 10 };
    struct Person p2 = { NULL, "bbb", 20 };
    struct Person p3 = { NULL, "ccc", 30 };
    struct Person p4 = { NULL, "ddd", 40 };
    struct Person p5 = { NULL, "eee", 50 };

    //初始化链式栈
    LinkStack stack = Init_LinkStack();
    //数据入栈
    Push_LinkStack(stack, &p1);
    Push_LinkStack(stack, &p2);
    Push_LinkStack(stack, &p3);
    Push_LinkStack(stack, &p4);
    Push_LinkStack(stack, &p5);
    //输出栈容器中元素
    while (Size_LinkStack(stack) > 0){
        
        //获得栈顶元素
        struct Person *person = (struct Person *)Top_LinkStack(stack);
        //打印
        printf("Name:%s Age:%d\n", person->name, person->age);
        //弹出栈顶元素
        Pop_LinkStack(stack);
        printf("Size:%d\n", Size_LinkStack(stack));

    }
    printf("----------------\n");
    printf("Size:%d\n", Size_LinkStack(stack));

    //销毁栈
    Destroy_LinkStack(stack);
}

int main(){

    test();

    system("pause");
    return EXIT_SUCCESS;
}

 

以链表作为底层容器,实现栈的操作:

容器头文件和头文件的实现:见数据结构链表的实现

栈的头文件:

#pragma once

#include"LinkList.h"

struct StackNode{
    struct LinkNode node;
};

typedef void *LinkStack;

//初始化
LinkStack Init_LinkStack();
//入栈
void Push_LinkStack(LinkStack stack, void *data);
//出栈
void Pop_LinkStack(LinkStack stack);
//获得栈顶元素
void *Top_LinkStack(LinkStack stack);
//大小
int Size_LinkStack(LinkStack stack);
//销毁栈
void Destroy_LinkStack(LinkStack stack);

 

栈的头文件实现:

#include"LinkStack.h"

//初始化
LinkStack Init_LinkStack(){
    return Init_LinkList();
}
//入栈
void Push_LinkStack(LinkStack stack, void *data){
    Insert_LinkList(stack, 0, data);
}
//出栈
void Pop_LinkStack(LinkStack stack){
    RemoveByPos_LinkList(stack, 0);
}
//获得栈顶元素
void *Top_LinkStack(LinkStack stack){
    return Get_LinkList(stack, 0);
}
//大小
int Size_LinkStack(LinkStack stack){
    return Size_LinkList(stack);
}
//销毁栈
void Destroy_LinkStack(LinkStack stack){
    Destroy_LinkList(stack);
}

 

测试代码:

define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"LinkStack.h"

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

void test(){

    //创建测试数据
    struct Person p1 = { NULL, "aaa", 10 };
    struct Person p2 = { NULL, "bbb", 20 };
    struct Person p3 = { NULL, "ccc", 30 };
    struct Person p4 = { NULL, "ddd", 40 };
    struct Person p5 = { NULL, "eee", 50 };
    //初始化栈
    LinkStack stack = Init_LinkStack();
    //数据入栈
    Push_LinkStack(stack , &p1);
    Push_LinkStack(stack, &p2);
    Push_LinkStack(stack, &p3);
    Push_LinkStack(stack, &p4);
    Push_LinkStack(stack, &p5);
    //输出栈中元素
    while (Size_LinkStack(stack) > 0){
    
        //获得栈顶元素
        struct Person *person = (struct Person*)Top_LinkStack(stack);
        //输出元素
        printf("Name:%s Age:%d\n",person->name,person->age);
        //弹出栈顶元素
        Pop_LinkStack(stack);

    }

    printf("Size%d\n",Size_LinkStack(stack));

    //销毁栈
    Destroy_LinkStack(stack);
}

int main(){

    test();

    system("pause");
    return EXIT_SUCCESS;
}

 

栈的实例应用与括号匹配

引用栈的顺序存储,实现括号匹配问题查找:

头文件:

#pragma once

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

#define MAX 1024

//顺序栈
struct SeqStack{
    void *data[MAX];
    int size;
};

#ifdef __cplusplus
extern "C"{
#endif

    //初始化栈
    void *Init_SeqStack();
    //入栈
    void Push_SeqStack(void *stack, void *data);
    //出栈
    void Pop_SeqStack(void *stack);
    //获得大小
    int Size_SeqStack(void *stack);
    //获得栈顶元素
    void *Top_SeqStack(void *stack);
    //销毁栈
    void Destroy_SeqStack(void *stack);

 

头文件实现:

#include"SeqStack.h"

//初始化栈
void *Init_SeqStack(){
    struct SeqStack *stack = malloc(sizeof(struct SeqStack));
    stack->size = 0; 
    for (int i = 0; i < MAX; i ++){
        stack->data[i] = 0;
    }

    return stack;
}
//入栈
void Push_SeqStack(void *stack, void *data){
    if (0 == stack){
        return;
    }
    if (0 == data){
        return;
    }
    struct SeqStack *s = (struct SeqStack *)stack;

    if (s->size == MAX){
        return;
    }

    s->data[s->size] = data;
    s->size++;
}
//出栈
void Pop_SeqStack(void *stack){

    if (0 == stack){
        return;
    }
    struct SeqStack *s = (struct SeqStack *)stack;
    s->size--;
}
//获得大小
int Size_SeqStack(void *stack){
    if (0 == stack){
        return -1;
    }
    struct SeqStack *s = (struct SeqStack *)stack;
    return s->size;
}
//获得栈顶元素
void *Top_SeqStack(void *stack){
    if (0 == stack){
        return NULL;
    }
    struct SeqStack *s = (struct SeqStack *)stack;
    return s->data[s->size - 1];
}
//销毁栈
void Destroy_SeqStack(void *stack){
    if (0 == stack){
        return;
    }
    free(stack);
}

 

测试函数:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"SeqStack.h"

int IsLeft(char ch){
    return ch == '(';
}

int IsRight(char ch){
    return ch == ')';
}

void printError(const char *str,const char *errMsg, const char * p){
    printf("Error:%s\n",errMsg);
    printf("%s\n",str);
    int len = p - str;
    for (int i = 0; i < len; i ++){
        printf(" ");
    }
    printf("A\n");
}

void test(){

    const char *str = "5+)5*(6)+9/(3*1)-(1)+3()";
    //初始化栈
    void *stack = Init_SeqStack();

    char *p = (char *)str;
    while (*p != '\0'){
    
        //如果是左括号,直接入栈
        if (IsLeft(*p)){
            Push_SeqStack(stack, p);
        }

        //如果是右括号,会有两种情况出现: 1栈不为空,匹配成功,把栈中当前字符弹出
                                  //2栈不为空,右括号没有匹配左括号
        if (IsRight(*p)){
            
            if (Size_SeqStack(stack) > 0){
                Pop_SeqStack(stack);
            }
            else{
                printError(str, "没有匹配的左括号!", p);
            }
        }

        p++;
    }

    //判断栈是否为空
    while (Size_SeqStack(stack) > 0){
        
        //获得栈顶元素
        char *pChar = (char *)Top_SeqStack(stack);
        //弹出栈顶元素
        Pop_SeqStack(stack);
        //输出错误信息
        printError(str, "没有匹配的右括号!", pChar);
    }

}

int main(){

    test();

    system("pause");
    return EXIT_SUCCESS;
}

传统链表实现与Linux内核链表 

头文件:

#pragma once

#include<stdlib.h>


//链表结点
struct LinkNode{
    void *data;
    struct LinkNode *next;
};

//链表
struct _Linklist{
    struct LinkNode header;
    int size; //链表结点的数目
};

typedef void *LinkList;

#ifdef __cplusplus
extern "C" {
#endif

    //初始化链表
    LinkList Init_LinkList();
    //指定位置插入
    int InsertByPos_LinkList(LinkList list, int pos, void *data);
    //头插
    int PushFront_LinkList(LinkList list, void *data);
    //尾插
    int PushBack_LinkList(LinkList list, void *data);
    //在指定值的前面插入
    int InsertByVal_LinkList(LinkList list, void *oldval, void *newval, int(*isequal)(void*,void*));
    //指定位置删除
    int RemoveByPos_LinkList(LinkList list, int pos);
    //根据值删除
    int RemoveByVal_LinkList(LinkList list, void *data, int(*compare)(void *, void *));
    //头删
    void PopFront_LinkList(LinkList list);
    //尾删
    void PopBack_LinkList(LinkList list);
    //遍历
    void Foreach_LinkList(LinkList list, void(*foreach)(void *));
    //销毁
    void Destroy_LinkList(LinkList list);

#ifdef __cplusplus
}
#endif

头文件实现:

#include"LinkList.h"


//初始化链表
LinkList Init_LinkList(){

    struct _Linklist *list = malloc(sizeof(struct _Linklist));
    if (NULL == list){
        return NULL;
    }

    list->header.data = NULL;
    list->header.next = NULL;
    list->size = 0;

    return list;
}
//指定位置插入 0代表插入到第一个位置
int InsertByPos_LinkList(LinkList list, int pos, void *data){

    if (NULL == list){
        return -1;
    }

    if (NULL == data){
        return -2;
    }

    struct _Linklist *llist = (struct _Linklist *)list;

    if (pos < 0 || pos > llist->size){
        pos = llist->size;
    }

    //辅助指针变量
    struct LinkNode *pCurrent = &(llist->header);
    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;

    //size
    llist->size++;

    return 0;
}
//头插
int PushFront_LinkList(LinkList list, void *data){
    return InsertByPos_LinkList(list, 0, data);
}
//尾插
int PushBack_LinkList(LinkList list, void *data){
    if (NULL == list){
        return -1;
    }
    struct _Linklist *llist = (struct _Linklist *)list;
    return InsertByPos_LinkList(list,llist->size - 1,data);
}
//在指定值的前面插入
int InsertByVal_LinkList(LinkList list, void *oldval, void *newval, int(*isequal)(void*, void*)){
    if(NULL ==list){
        return -1;
    }

    if (NULL == oldval){
        return -2;
    }

    if (NULL == newval){
        return -3;
    }

    if (NULL == isequal){
        return -4;
    }

    struct _Linklist *llist = (struct _Linklist *)list;

    //辅助指针变量
    struct LinkNode *pPrev = &(llist->header);
    struct LinkNode *pCurrent = pPrev->next;
    while (pCurrent != NULL){
        
        if (isequal(pCurrent->data, oldval)){
            
            //创建新结点
            struct LinkNode *newnode = malloc(sizeof(struct LinkNode));
            newnode->data = newval;
            newnode->next = NULL;

            //新结点入链表
            pPrev->next = newnode;
            newnode->next = pCurrent;

            llist->size++;

            break;
        }

        pPrev = pCurrent;
        pCurrent = pCurrent->next;
    }
    
    return 0;
}
//指定位置删除
int RemoveByPos_LinkList(LinkList list, int pos){

    if (NULL == list){
        return -1;
    }

    struct _Linklist *llist = (struct _Linklist *)list;

    if (llist->size == 0){
        return 0;
    }

    if (pos < 0 || pos > llist->size - 1){
        return 0;
    }

    //辅助指针变量
    //找到待删除结点的前一个结点
    struct LinkNode *pCurrent = &(llist->header);
    for (int i = 0; i < pos;i ++){
        pCurrent = pCurrent->next;
    }

    //缓存下待删除结点
    struct LinkNode *pDel = pCurrent->next;
    //重新建立待删除结点的前驱后继结点关系
    pCurrent->next = pDel->next;
    //删除结点内存
    free(pDel);
    pDel = NULL;

    llist->size--;

    return 0;
}
//根据值删除
int RemoveByVal_LinkList(LinkList list, void *data, int(*compare)(void *, void *)){

    if (NULL == list){
        return -1;
    }

    if (NULL == data){
        return -2;
    }

    if (NULL == compare){
        return -3;
    }

    struct _Linklist *llist = (struct _Linklist *)list;
    //辅助指针变量
    struct LinkNode *pPrev = &(llist->header);
    struct LinkNode *pCurrent = pPrev->next;

    while (pCurrent != NULL){
        
        if (compare(pCurrent->data, data)){
            
            pPrev->next = pCurrent->next;
            free(pCurrent);
            llist->size--;
            break;
        }

        pPrev = pCurrent;
        pCurrent = pPrev->next;
    
    }

    return 0;
}
//头删
void PopFront_LinkList(LinkList list){
    RemoveByPos_LinkList(list, 0);
}
//尾删
void PopBack_LinkList(LinkList list){
    if (NULL == list){
        return;
    }
    struct _Linklist *llist = (struct _Linklist *)list;
    RemoveByPos_LinkList(list, llist->size - 1);
}
//遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *)){

    if (NULL == list){
        return;
    }

    if (NULL ==    foreach){
        return;
    }

    struct _Linklist *llist = (struct _Linklist *)list;

    //辅助指针变量
    struct LinkNode *pCurrent = llist->header.next;
    while (pCurrent != NULL){
        foreach(pCurrent->data);
        pCurrent = pCurrent->next;
    }

}
//销毁
void Destroy_LinkList(LinkList list){

    if (NULL == list){
        return;
    }

    struct _Linklist *llist = (struct _Linklist *)list;

    //辅助指针变量
    struct LinkNode *pCurrent = llist->header.next;
    while (pCurrent != NULL){
        
        //缓存下一个结点
        struct LinkNode *pNext = pCurrent->next;
        //释放当前结点内存
        free(pCurrent);
        //指针移动到下一个结点的位置
        pCurrent = pNext;

    }

    free(llist);
    llist = NULL;
}

测试代码:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"LinkList.h"

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


void MyPrint(void *data){
    struct Person *person = (struct Person *)data;
    printf("Name:%s Age:%d\n", person->name,person->age);
}

int MyCompare(void *d1,void *d2){
    struct Person *p1 = (struct Person *)d1;
    struct Person *p2 = (struct Person *)d2;
    return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}

void test(){

    //创建测试数据
    struct Person p1 = { "aaa", 10 };
    struct Person p2 = { "bbb", 20 };
    struct Person p3 = { "ccc", 30 };
    struct Person p4 = { "ddd", 40 };
    struct Person p5 = { "eee", 50 };
    struct Person p6 = { "fff", 60 };
    struct Person p7 = { "ggg", 70 };
    
    //初始化链表
    LinkList list = Init_LinkList();
    //将数据插入链表
    InsertByPos_LinkList(list, 0, &p1);
    InsertByPos_LinkList(list, 0, &p2);
    InsertByPos_LinkList(list, 0, &p3); 
    InsertByPos_LinkList(list, 1, &p4);
    InsertByPos_LinkList(list, 0, &p5);
    InsertByPos_LinkList(list, 0, &p6);
    //遍历 6 5 3 4 2 1
    Foreach_LinkList(list, MyPrint);
    printf("-------------------\n");
    printf("在name为ccc,age为30的数据前面插入:\n");
    InsertByVal_LinkList(list, &p3, &p7, MyCompare);
    Foreach_LinkList(list, MyPrint);
    printf("删除位置4的数据:\n");
    RemoveByPos_LinkList(list,4);
    Foreach_LinkList(list, MyPrint);
    printf("删除name为ggg age为70的数据:\n");
    RemoveByVal_LinkList(list, &p7, MyCompare);
    Foreach_LinkList(list, MyPrint);

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

int main(){

    test();

    system("pause");
    return EXIT_SUCCESS;
}

 

链表版本二:通过修改指针的指向的区域的大小,实现数据链接,给用户使用

头文件:

#pragma once

#include<stdlib.h>

//链表小节点

//目的 : 第一,让用户数据包含 第二,我需要把用户指针类型转换成struct LinkNode*类型
struct LinkNode{
    struct LinkNode *next;
};

//链表结构体
struct LList{
    struct LinkNode header;
    int size;
};

typedef void *LinkList;

//初始化
LinkList Init_LinkList();

//指定位置插入
void Insert_LinkList(LinkList list, int pos, struct LinkNode *data);
//位置删除
void RemoveByPos_LinkList(LinkList list, int pos);
//遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *));

//销毁
void Destroy_LinkList(LinkList list);

 

头文件实现:

#include"LinkList.h"


//初始化
LinkList Init_LinkList(){

    struct LList *list = malloc(sizeof(struct LList));
    if (NULL == list){
        return NULL;
    }
    list->header.next = NULL;
    list->size = 0;

    return list;
}
//指定位置插入
void Insert_LinkList(LinkList list, int pos, struct LinkNode *data){
    
    if (NULL == list){
        return;
    }

    if (NULL == data){
        return;
    }
    
    struct LList *llist = (struct LList *)list;

    if (pos < 0 || pos >llist->size){
        pos = llist->size;
    }

    //查找pos位置前一个位置的节点
    struct LinkNode *pCurrent = &(llist->header);
    for (int i = 0; i < pos;i ++){
        pCurrent = pCurrent->next;
    }

    //将新节点插入到链表
    data->next = pCurrent->next;
    pCurrent->next = data;

    llist->size++;
}

//位置删除
void RemoveByPos_LinkList(LinkList list, int pos){

    if (NULL ==list){
        return;
    }

    struct LList *llist = (struct LList *)list;


    if (llist->size == 0){
        return;
    }

    if (pos < 0 || pos > llist->size - 1){
        return;
    }


    //找到pos位置的前一个节点
    struct LinkNode *pCurrent = &(llist->header);
    for (int i = 0; i < pos; i ++){
        pCurrent = pCurrent->next;
    }

    //缓存下待删除节点
    struct LinkNode *pDel = pCurrent->next;
    //重新建立待删除的节点前驱后继节点关系
    pCurrent->next = pDel->next;

    llist->size--;
}

//遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *)){
    if (NULL == list){
        return;
    }

    struct LList *llist = (struct LList *)list;
    //辅助指针变量
    struct LinkNode *pCurrent = llist->header.next;
    while (pCurrent != NULL){
        foreach(pCurrent);
        pCurrent = pCurrent->next;
    }
}

测试函数:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"LinkList.h"

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

void MyPrint(void *data){
    struct Person *person = (struct Person *)data;
    printf("Name:%s Age:%d\n",person->name,person->age);
}

void ChanageValue(void *data){
    struct Person *person = (struct Person *)data;
    person->age += 100;
}

//#define ISSTACK

void test(){

    //创建测试数据
#ifdef ISSTACK
    struct Person p1 = { NULL , "aaa", 10 };
    struct Person p2 = { NULL , "bbb", 20 };
    struct Person p3 = { NULL , "ccc", 30 };
    struct Person p4 = { NULL , "ddd", 40 };
    struct Person p5 = { NULL , "eee", 50 };
#else
    struct Person *p1 = malloc(sizeof(struct Person));
    struct Person *p2 = malloc(sizeof(struct Person));
    struct Person *p3 = malloc(sizeof(struct Person));
    struct Person *p4 = malloc(sizeof(struct Person));
    struct Person *p5 = malloc(sizeof(struct Person));


    strcpy(p1->name, "aaa");
    strcpy(p2->name, "bbb");
    strcpy(p3->name, "ccc");
    strcpy(p4->name, "ddd");
    strcpy(p5->name, "eee");

    p1->age = 10;
    p2->age = 20;
    p3->age = 30;
    p4->age = 40;
    p5->age = 50;

#endif

    //初始化链表
    LinkList list = Init_LinkList();
#ifdef ISSTACK
    //数据插入到链表
    Insert_LinkList(list, 0, (struct LinkNode *)&p1);
    Insert_LinkList(list, 0, (struct LinkNode *)&p2);
    Insert_LinkList(list, 0, (struct LinkNode *)&p3);
    Insert_LinkList(list, 0, (struct LinkNode *)&p4);
    Insert_LinkList(list, 0, (struct LinkNode *)&p5);
#else
    Insert_LinkList(list, 0, (struct LinkNode *)p1);
    Insert_LinkList(list, 0, (struct LinkNode *)p2);
    Insert_LinkList(list, 0, (struct LinkNode *)p3);
    Insert_LinkList(list, 0, (struct LinkNode *)p4);
    Insert_LinkList(list, 0, (struct LinkNode *)p5);
#endif
    //遍历
    Foreach_LinkList(list, MyPrint);

    //删除2号位置
    printf("------------------\n");
    RemoveByPos_LinkList(list, 3);
    Foreach_LinkList(list, MyPrint);

    //遍历修改数据
    printf("---------------------\n");
    //Foreach_LinkList(list, ChanageValue);
    //Foreach_LinkList(list, MyPrint);

    //销毁链表
    Destroy_LinkList(list);

    free(p1);
    free(p2);
    free(p3);
    free(p4);
    free(p5);

}

int main(){

    test();

    system("pause");
    return EXIT_SUCCESS;
}

 

以链表为底层容器实现栈

头文件:

容器头文件:

#pragma once

#include<stdlib.h>

//链表小节点

//目的 : 第一,让用户数据包含 第二,我需要把用户指针类型转换成struct LinkNode*类型
struct LinkNode{
struct LinkNode *next;
};

//链表结构体
struct LList{
struct LinkNode header;
int size;
};

typedef void *LinkList;

//初始化
LinkList Init_LinkList();

//指定位置插入
void Insert_LinkList(LinkList list, int pos, struct LinkNode *data);
//位置删除
void RemoveByPos_LinkList(LinkList list, int pos);
//遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *));
//根据位置获得值
void *Get_LinkList(LinkList list,int pos);
int Size_LinkList(LinkList list);


//销毁
void Destroy_LinkList(LinkList list);

 

栈头文件:

#pragma once

#include"LinkList.h"

struct StackNode{
    struct LinkNode node;
};

typedef void *LinkStack;

//初始化
LinkStack Init_LinkStack();
//入栈
void Push_LinkStack(LinkStack stack, void *data);
//出栈
void Pop_LinkStack(LinkStack stack);
//获得栈顶元素
void *Top_LinkStack(LinkStack stack);
//大小
int Size_LinkStack(LinkStack stack);
//销毁栈
void Destroy_LinkStack(LinkStack stack);

 

头文件实现:

容器头文件实现:

#include"LinkList.h"


//初始化
LinkList Init_LinkList(){

    struct LList *list = malloc(sizeof(struct LList));
    if (NULL == list){
        return NULL;
    }
    list->header.next = NULL;
    list->size = 0;

    return list;
}
//指定位置插入
void Insert_LinkList(LinkList list, int pos, struct LinkNode *data){
    
    if (NULL == list){
        return;
    }

    if (NULL == data){
        return;
    }
    
    struct LList *llist = (struct LList *)list;

    if (pos < 0 || pos >llist->size){
        pos = llist->size;
    }

    //查找pos位置前一个位置的节点
    struct LinkNode *pCurrent = &(llist->header);
    for (int i = 0; i < pos;i ++){
        pCurrent = pCurrent->next;
    }

    //将新节点插入到链表
    data->next = pCurrent->next;
    pCurrent->next = data;

    llist->size++;
}

//位置删除
void RemoveByPos_LinkList(LinkList list, int pos){

    if (NULL ==list){
        return;
    }

    struct LList *llist = (struct LList *)list;


    if (llist->size == 0){
        return;
    }

    if (pos < 0 || pos > llist->size - 1){
        return;
    }


    //找到pos位置的前一个节点
    struct LinkNode *pCurrent = &(llist->header);
    for (int i = 0; i < pos; i ++){
        pCurrent = pCurrent->next;
    }

    //缓存下待删除节点
    struct LinkNode *pDel = pCurrent->next;
    //重新建立待删除的节点前驱后继节点关系
    pCurrent->next = pDel->next;

    llist->size--;
}


//根据位置获得值
void *Get_LinkList(LinkList list, int pos){
    if (NULL == list){
        return NULL;
    }

    struct LList *llist = (struct LList *)list;
    if (pos < 0 || pos > llist->size - 1){
        return NULL;
    }

    //辅助指针变量
    struct LinkNode *pCurrent = &(llist->header);
    for (int i = 0; i < pos; i++){
        pCurrent = pCurrent->next;
    }


    return pCurrent->next;
}

int Size_LinkList(LinkList list){
    if (NULL == list){
        return -1;
    }

    struct LList *llist = (struct LList *)list;
    return llist->size;
}


//遍历
void Foreach_LinkList(LinkList list, void(*foreach)(void *)){
    if (NULL == list){
        return;
    }

    struct LList *llist = (struct LList *)list;
    //辅助指针变量
    struct LinkNode *pCurrent = llist->header.next;
    while (pCurrent != NULL){
        foreach(pCurrent);
        pCurrent = pCurrent->next;
    }
}

//销毁
void Destroy_LinkList(LinkList list){
    if (NULL == list){
        return;
    }

    free(list);
    list = NULL;
}

栈头文件实现:

#include"LinkStack.h"

//初始化
LinkStack Init_LinkStack(){
    return Init_LinkList();
}
//入栈
void Push_LinkStack(LinkStack stack, void *data){
    Insert_LinkList(stack, 0, data);
}
//出栈
void Pop_LinkStack(LinkStack stack){
    RemoveByPos_LinkList(stack, 0);
}
//获得栈顶元素
void *Top_LinkStack(LinkStack stack){
    return Get_LinkList(stack, 0);
}
//大小
int Size_LinkStack(LinkStack stack){
    return Size_LinkList(stack);
}
//销毁栈
void Destroy_LinkStack(LinkStack stack){
    Destroy_LinkList(stack);
}

 

测试文件

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"LinkStack.h"

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

void test(){

    //创建测试数据
    struct Person p1 = { NULL, "aaa", 10 };
    struct Person p2 = { NULL, "bbb", 20 };
    struct Person p3 = { NULL, "ccc", 30 };
    struct Person p4 = { NULL, "ddd", 40 };
    struct Person p5 = { NULL, "eee", 50 };
    //初始化栈
    LinkStack stack = Init_LinkStack();
    //数据入栈
    Push_LinkStack(stack , &p1);
    Push_LinkStack(stack, &p2);
    Push_LinkStack(stack, &p3);
    Push_LinkStack(stack, &p4);
    Push_LinkStack(stack, &p5);
    //输出栈中元素
    while (Size_LinkStack(stack) > 0){
    
        //获得栈顶元素
        struct Person *person = (struct Person*)Top_LinkStack(stack);
        //输出元素
        printf("Name:%s Age:%d\n",person->name,person->age);
        //弹出栈顶元素
        Pop_LinkStack(stack);

    }

    printf("Size%d\n",Size_LinkStack(stack));

    //销毁栈
    Destroy_LinkStack(stack);
}

int main(){

    test();

    system("pause");
    return EXIT_SUCCESS;
}

 二叉树

二叉树性质

n 性质1: 在二叉树的第i层上至多有2i-1个结点(i>0)

n 性质2: 深度为k的二叉树至多有2k-1个结点(k>0)

n 性质3: 对于任何一棵二叉树,若度为2的结点数有n2个,则叶子数(n0)必定为n2+1 (即n0=n2+1)

 

二叉树的递归遍历源码:分为先序遍历:根 左 右 ;中序遍历:左 根 右;后续遍历:左 右 根

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

//二叉树节点
struct BiNode{
    char ch;
    struct BiNode *lchild;
    struct BiNode *rchild;
};

//二叉树的递归遍历先序
void recursion(struct BiNode *root){

    if (NULL == root){
        return;
    }

    //再访问左子树
    recursion(root->lchild);//printf 先序遍历
    //再访问右子树
    recursion(root->rchild);// printf 中顺序遍历
    //先访问根节点
    printf("%c ", root->ch);// printf  后续遍历
}

void test(){

    //二叉树节点
    struct BiNode node1 = { 'A', NULL, NULL };
    struct BiNode node2 = { 'B', NULL, NULL };
    struct BiNode node3 = { 'C', NULL, NULL };
    struct BiNode node4 = { 'D', NULL, NULL };
    struct BiNode node5 = { 'E', NULL, NULL };
    struct BiNode node6 = { 'F', NULL, NULL };
    struct BiNode node7 = { 'G', NULL, NULL };
    struct BiNode node8 = { 'H', NULL, NULL };

    node1.lchild = &node2;
    node1.rchild = &node6;
    node2.rchild = &node3;
    node3.lchild = &node4;
    node3.rchild = &node5;
    node6.rchild = &node7;
    node7.lchild = &node8;

    //遍历二叉树
    recursion(&node1);
}

int main(){

    test();

    system("pause");
    return EXIT_SUCCESS;
}

 

通过栈实现二叉树的非递归遍历:

见数据结构 栈的实现

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"SeqStack.h"
#include<stdbool.h>

//二叉树节点
struct BiNode{
    char ch;
    struct BiNode *lchild;
    struct BiNode *rchild;
};

struct Info{
    struct BiNode *node;
    bool flag;
};

struct Info *CreateInfo(struct BiNode *node,bool flag){
    struct Info *info = malloc(sizeof(struct Info));
    info->node = node;
    info->flag = flag;

    return info;
}


void nonrecursion(struct BiNode *root){
    
    //初始化stack
    void *stack = Init_SeqStack();
    //1. 先把根节点入stack
    Push_SeqStack(stack, CreateInfo(root, false));

    while (Size_SeqStack(stack) > 0){
        
        //2. 获得stack顶元素
        struct Info *info = (struct Info *)Top_SeqStack(stack);
        Pop_SeqStack(stack);

        //3. 判断当前节点的flag是否为true,true:直接输出。false:左子树和右子树分别压stack,当前节点二次入stack
        if(info->flag){
            printf("%c ",info->node->ch);
            free(info);
            continue;
        }


        
        //右子树入stack
        if (info->node->rchild != NULL){
            Push_SeqStack(stack, CreateInfo(info->node->rchild, false));
        }

        //根节点入stack
        info->flag = true;
        Push_SeqStack(stack, info);


        //左子树入stack
        if (info->node->lchild != NULL){
            Push_SeqStack(stack, CreateInfo(info->node->lchild, false));
        }


    }

}

void test(){

    //二叉树节点
    struct BiNode node1 = { 'A', NULL, NULL };
    struct BiNode node2 = { 'B', NULL, NULL };
    struct BiNode node3 = { 'C', NULL, NULL };
    struct BiNode node4 = { 'D', NULL, NULL };
    struct BiNode node5 = { 'E', NULL, NULL };
    struct BiNode node6 = { 'F', NULL, NULL };
    struct BiNode node7 = { 'G', NULL, NULL };
    struct BiNode node8 = { 'H', NULL, NULL };

    node1.lchild = &node2;
    node1.rchild = &node6;
    node2.rchild = &node3;
    node3.lchild = &node4;
    node3.rchild = &node5;
    node6.rchild = &node7;
    node7.lchild = &node8;

    nonrecursion(&node1);

}



int main(){

    test();


    

    system("pause");
    return EXIT_SUCCESS;
}

 

求二叉数的叶子节点函数:

void caculateLeafNums(struct BiNode *root,int *num){

    if (NULL == root){
        return;
    }

    if (root->lchild == NULL && root->rchild == NULL){
        (*num)++;
    }
    
    //遍历左子树
    caculateLeafNums(root->lchild, num);
    //遍历右子树
    caculateLeafNums(root->rchild, num);

}

 

二叉树的拷贝、释放、二叉树高度函数:

//拷贝二叉树
struct BiNode *copyTree(struct BiNode *root){

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

    //递归拷贝左子树
    struct BiNode *lchild = copyTree(root->lchild);
    //递归拷贝右子树
    struct BiNode *rchild = copyTree(root->rchild);

    //拷贝当前节点
    struct BiNode *newnode = malloc(sizeof(struct BiNode));
    printf("%c ",root->ch);
    newnode->ch = root->ch;
    newnode->lchild = lchild;
    newnode->rchild = rchild;

    return newnode;
}

//释放二叉树内存
void freeSpace(struct BiNode *root){
    if (NULL == root){
        return;
    }

    //释放左子树
    freeSpace(root->lchild);
    //释放右子树
    freeSpace(root->rchild);
    //释放根节点
    free(root);

}

//递归遍历
void foreach(struct BiNode *root){
    if (NULL == root){
        return;
    }

    printf("%c ",root->ch);
    foreach(root->lchild);
    foreach(root->rchild);
}

//求树的高度
int caculateTreeHeight(struct BiNode *root){

    if (NULL == root){
        return 0;
    }


    //求左子树的高度
    int lheight = caculateTreeHeight(root->lchild);
    //求右子树的高度
    int rheight = caculateTreeHeight(root->rchild);

    int height = lheight > rheight ? lheight + 1 : rheight + 1;

    return height;
}

 

posted @ 2017-04-28 18:52  天码丶行满  阅读(597)  评论(0编辑  收藏  举报