总结3


数据结构
从结构上看:
  1、数组:内存连续
  2、链表:内存不连续
从功能上看:
  1、线性:插入数据的顺序,与位置直接相关:vector list queue stack
  2、关联:插入数据的值,与位置直接相关:map hashmap

线性
关联

实现升序动态数组:增删查询

实现升序动态数组的关键是realloc和memmove和memcpy

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

typedef struct Array{
    void* data;//数组内存
    int size;//单元大小
    int idx;//当前插入的数据个数
    int capa;//当前分配的长度
}array_t;

array_t* arrayInit(int size);//初始化数组是什么数据类型
void arrayFree(array_t* array);//释放一个数据
void* arrayInsert(array_t* array, const void* data, int (*compare)(const void*,
            const void*));//插入一个数据,数据保持升序
void arrayRemove(array_t* array, const void* data, int(*compare)(const void*,
            const void*));
const void* arraySelect(array_t* array, const void* data, int(*compare)(const
            void*, const void*));

int compareInt(const void* d1, const void* d2)
{
    return *(const int*)d1 - *(const int*)d2;
}

int main()
{
    srand(time(0));//随机种子
    array_t* array = arrayInit(sizeof(int));

    int i = 0, data = 0;
    for(i = 0; i < 10; i++){
        arrayInsert(array, &i, compareInt);
    }

    data = 5;
    arrayRemove(array, &data, compareInt);
    data = 6;
    const int* p = (const int*)arraySelect(array, &data, compareInt);
    printf("::%d\n", data);
    for(i = 0; i < array->idx; i++){
        printf("%d\n", *(int*)(array->data + i * array->size));
    }

    arrayFree(array);
    array = NULL;

    return 0;
}

const void* arraySelect(array_t* array, const void* data, int(*compare)(const
            void*, const void*))
{
    if(array == NULL || data == NULL || compare == NULL) return NULL;

    int l = 0, r = array->idx - 1;
    while(l <= r){
        int m = (l + r) / 2;
        if(compare(data, array->data + m * array->size) == 0){
            //返回即可
            return array->data + m * array->size;
        }else if(compare(data, array->data + m * array->size) > 0)
        {
            l = m + 1;
        }else{
            r = m -1;
        }
    }

    return NULL;
}
void arrayRemove(array_t* array, const void* data, int(*compare)(const void*,
            const void*))
{
    if(array == NULL || data == NULL || compare == NULL) return;

    int l = 0, r = array->idx - 1;
    while(l <= r){
        int m = (l + r) / 2;
        if(compare(data, array->data + m * array->size) == 0){
            //删除即可
            int len = array->idx - m - 1;
            if(len > 0) memmove(array->data + m * array->size, array->data + (m
                        + 1) * array->size, len * array->size);
            array->idx--;
            memset(array->data + array->idx * array->size, 0, array->size);
            return;
        }else if(compare(data, array->data + m * array->size) > 0){
            l = m + 1;
        }else{
            r = m - 1;
        }
    }

    return;
}

void* arrayInsert(array_t* array, const void* data, int (*compare)(const void*,
            const void*))
{
    /*健壮性检查*/
    if(array == NULL || data == NULL || compare == NULL) return NULL;
    
    /*扩容*/
    if(array->idx == array->capa){
        array->capa *= 2;
        array->data = realloc(array->data, array->capa * array->size);
        memset(array->data + array->idx * array->size, 0, array->idx *
                array->size);
    }

    int i = 0;
    while(i < array->idx && compare(data, array->data + i * array->size) > 0){
        ++i;
    }

    int len = array->idx - i;
    if(len > 0) memmove(array->data + (i + 1) * array->size, array->data + i *
            array->size, len * array->size);
    memcpy(array->data + i * array->size, data, array->size);
    array->idx++;
}

void arrayFree(array_t* array)
{
    /*健壮性检查*/
    if(array == NULL) return;

    free(array->data);//先释放数据域
    free(array);//再释放节点域
}

array_t* arrayInit(int size)
{
    /*健壮性检查*/
    if(size < 0) return NULL;
    array_t* array = (array_t*)malloc(sizeof(array_t));//节点域
    memset(array, 0, sizeof(array_t));//初始化节点域

    array->size = size;//单元大小
    array->idx = 0;//当前插入的数据有0个
    array->capa = 1;//当前分配的长度为1
    array->data = malloc(array->capa * size);//数据域

    return array;
}

在这里插入图片描述

链表拆分和归并

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//1、链表拆分,链表一分为二,快慢指针
//2、链表归并,假设两个链表已知升序,合并两张链表后保持升序

typedef struct Node{
    int data;
    struct Node* next;
}node_t;

node_t* listPushBack(node_t* head, int data);
node_t* listPopBack(node_t* head);
void listFree(node_t* head);
node_t* listSeperate(node_t* head);
node_t* listMerge(node_t* head1, node_t* head2);
node_t* listMergeSort(node_t* head);

int main(void)
{
    srand(time(0));
    node_t* head = NULL;
    int i = 0;
    for(i = 0; i < 10; i++){
        head = listPushBack(head, rand() % 1000);
    }

    //排序
    head = listMergeSort(head);

    node_t* p = head;
    while(p){
        printf("%d\n", p->data);
        p = p->next;
    }

    listFree(head);

    return 0;
}
node_t* listMergeSort(node_t* head)
{
    if(head == NULL || head->next == NULL) return head;

    node_t* h = listSeperate(head);

    head = listMergeSort(head);
    h = listMergeSort(h);

    return listMerge(head, h);
}

node_t* listMerge(node_t* head1, node_t* head2)
{
    node_t* p1 = head1, *p2 = head2;
    node_t node;
    node.next = NULL;
    node_t* p = &node;//p表示指向node中最后一个

    while(p1 != NULL && p2 != NULL){
        if(p1->data < p2->data){
            p->next = p1;
            p1 = p1->next;
        }else{
            p->next = p2;
            p2 = p2->next;
        }
        p = p->next;
    }

    if(p1 != NULL){
        p->next = p1;
    }else if(p2 != NULL){
        p->next = p2;
    }

    return node.next;
}

node_t* listSeperate(node_t* head)
{
    node_t node;
    node.next = head;

    node_t* p1 = &node, *p2 = &node;
    while(p1 != NULL){
        p1 = p1->next;
        if(p1 == NULL) break;
        p1 = p1->next;
        p2 = p2->next;
    }

    node_t* ret = p2->next;
    p2->next = NULL;

    return ret;
}
void listFree(node_t* head)
{
    node_t* p = head;
    while(p != NULL){
        node_t* tmp = p;
        p = p->next;
        free(tmp);
    }
}
node_t* listPopBack(node_t* head)
{
    if(head == NULL) return NULL;

    node_t node;
    node.next = head;

    node_t* pre = &node, *p = head;
    while(p->next != NULL){
        p = p->next;
        pre = pre->next;
    }

    pre->next = NULL;
    free(p);

    return node.next;
}
//返回头结点
node_t* listPushBack(node_t* head, int data)
{
    node_t* newNode = (node_t*)malloc(sizeof(node_t));
    memset(newNode, 0, sizeof(node_t));

    newNode->data = data;

    //尾插
    node_t node;
    node.next = head;//节点指向空

    node_t* p = &node;
    while(p->next != NULL){
        p = p->next;
    }

    p->next = newNode;
    newNode->next = NULL;

    return node.next;
}

在这里插入图片描述

带头结点的双向链表

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

typedef struct Node{
	struct Node* next;
	struct Node* prev;
	char data[0];
}node_t;

typedef struct List{
	node_t head;
	int size;
}list_t;

list_t*	listInit(int size);
void	listFree(list_t* list);
void*	listPushBack(list_t* list, const void* data);

int main(void)
{
	list_t* list = listInit(sizeof(int));

	int i = 0;
	for(i = 0; i < 10; i++){
		listPushBack(list, &i);
	}

	node_t* p = list->head.next;
	while(p != &(list->head)){
		printf("%d\n", *(int*)p->data);
		p = p->next;
	}

	listFree(list);

	return 0;
}

list_t*	listInit(int size)
{
	if(size < 0) return NULL;
	list_t* list = (list_t*)malloc(sizeof(list_t));
	memset(list, 0, sizeof(list_t));

	list->size = size;
	list->head.next = &(list->head);
	list->head.prev = &(list->head);

	return list;
}

void	listFree(list_t* list)
{
	if(list == NULL) return;

	node_t* p = list->head.next;
	while(p != &(list->head)){
		node_t* tmp = p;
		p = p->next;
		free(tmp);
	}
	free(list);
}

void*	listPushBack(list_t* list, const void* data)
{
	if(list == NULL || data == NULL) return NULL;

	//1. 创建新节点
	node_t* newNode = (node_t*)malloc(sizeof(node_t) + list->size);
	memcpy(newNode->data, data, list->size);

	newNode->prev = list->head.prev;
	list->head.prev->next = newNode;
	list->head.prev = newNode;
	newNode->next = &list->head;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值