数据结构
从结构上看:
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;
}