最近在看李先静先生的《系统程序员成长计划》,正好复习一下自己的C语言基础。李先生所认为的双向链表和动态数组是真实项目中最常见的应用我很赞同,还记得我第一个SIP TRUNK项目里电话请求就是用链表实现的队列。不过李先生讲的更加抽象,可能是因为他站在一个跨平台的思想高度来思考问题的,所以书中要求实现的双向链表和动态数组都是不限数据类型,我没有那么高的思想水平,就实现了一个整数的双向链表和动态数组,主要是练习练习,毕竟好久没有使用C语言编程了。
写着写着,我发现原来把它们写成通用的并不难,希望大家参考了我的后可以自己实现,把接口改为通用类型,当然虽然我自己测试过了但程序中的bug肯定还是不少的,我尽量改正吧!如果大家发现了新的bug可以马上告诉我,我立马修改,谢谢!
双向链表:
Line.h
- #ifdef _cplusplus
- extern "C" {
- #endif
- #define EMPTY 0
- #define HEAD 0
- #define TRUE 0
- #define FALSE 1
- #define ERRNUM 5
- #define LINEISNULL 0
- #define LOCALUPNODENUM 1
- #define MEMORYEMPTY 2
- #define NOLINE 3
- typedef struct _lineNode {
- int data;
- struct _lineNode *prep;
- struct _lineNode *next;
- }LineNode;
- typedef struct _lineHead {
- LineNode *head;
- int NodeNum;
- }LineHead;
- LineHead *CreateLine();
- void DeleteLine(LineHead *linehead);
- LineNode *CreateNode(int data);
- void PushNode(LineHead *linehead, LineNode *linenode);
- //调用者保障链表不为空
- LineNode *PopNode(LineHead *linehead);
- //调用者保障local小于linehead->NodeNum
- void InsertNode(LineHead *linehead, LineNode *linenode, int local);
- //调用者保障local小于linehead->NodeNum
- LineNode *GetNode(LineHead *linehead, int local);
- //调用者保障local小于linehead->NodeNum
- int GetNodeData(LineHead *linehead, int local);
- //回调函数由调用者完成
- //int ListForEach(LineHead *linehead, Callbcak visit, void *ctx);
- void ShowLine(LineHead *linehead);
- #ifdef _cplusplus
- }
- #endif
Line.c
- #include <stdio.h>
- #include <stdlib.h>
- #include "Line_1_1.h"
- char *errorstring[ERRNUM] = {"The line is null!", "local is upper than line's node number!",
- "Memory can't be alloced!", "Line has not created!"};
- LineHead *CreateLine()
- {
- LineHead *temp;
- temp = (LineHead *)malloc(sizeof(LineHead));
- if (NULL == temp)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[MEMORYEMPTY]);
- exit(0);
- }
- temp->head = NULL;
- temp->NodeNum = 0;
- return temp;
- }
- void DeleteLine(LineHead *linehead)
- {
- LineNode *temp;
- temp = linehead->head;
- while (NULL != temp)
- {
- linehead->head = linehead->head->next;
- linehead->NodeNum--;
- free(temp);
- temp = linehead->head;
- }
- free(linehead);
- }
- LineNode *CreateNode(int data)
- {
- LineNode *p;
- p = (LineNode *)malloc(sizeof(LineNode));
- if (NULL == p)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[MEMORYEMPTY]);
- exit(0);
- }
- p->data = data;
- p->next = p->prep = NULL;
- return p;
- }
- void PushNode(LineHead *linehead, LineNode *linenode)
- {
- LineNode *p, *prep = NULL;
- int i;
- //改为断言
- //######################
- if (NULL == linehead)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[NOLINE]);
- //return NULL;
- exit(0);
- }
- //######################
- p = linehead->head;
- for (i = 0; i < linehead->NodeNum; i++)
- {
- prep = p;
- p = p->next;
- }
- p = (LineNode *)malloc(sizeof(LineNode));
- if (NULL == p)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[MEMORYEMPTY]);
- exit(0);
- }
- if (EMPTY == linehead->NodeNum)
- {
- linehead->head = p;
- p->prep = NULL;
- }
- else
- {
- p->prep = prep;
- prep->next = p;
- }
- p->data = linenode->data;
- p->next = NULL;
- linehead->NodeNum++;
- }
- //调用者保障链表不为空
- LineNode *PopNode(LineHead *linehead)
- {
- LineNode *p;
- //改为断言
- //######################
- if (NULL == linehead)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[NOLINE]);
- //return NULL;
- exit(0);
- }
- //######################
- //改为断言
- //######################
- if (NULL == linehead->head)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[LINEISNULL]);
- //return NULL;
- exit(0);
- }
- //######################
- p = linehead->head;
- while (NULL != p->next)
- {
- p = p->next;
- }
- if (p == linehead->head)
- {
- linehead->head = NULL;
- }
- else
- {
- p->prep->next = NULL;
- }
- linehead->NodeNum--;
- //保障传出参数使用不会出现越权访问
- p->next = p->prep = NULL;
- return p;
- }
- //调用者保障local小于linehead->NodeNum
- void InsertNode(LineHead *linehead, LineNode *linenode, int local)
- {
- LineNode *p, *temp, *prep = NULL;
- int i;
- //改为断言
- //######################
- if (NULL == linehead)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[LINEISNULL]);
- //return NULL;
- exit(0);
- }
- //######################
- //改为断言
- //######################
- if (local >= linehead->NodeNum)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[LOCALUPNODENUM]);
- //return ERROR;
- exit(0);
- }
- //######################
- p = linehead->head;
- for (i = 0; i < local; i++)
- {
- prep = p;
- p = p->next;
- }
- temp = (LineNode *)malloc(sizeof(LineNode));
- if (NULL == temp)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[MEMORYEMPTY]);
- exit(0);
- }
- temp->data = linenode->data;
- if (HEAD == local)
- {
- linehead->head = temp;
- temp->prep = NULL;
- }
- else
- {
- prep->next = temp;
- temp->prep = prep;
- }
- p->prep = temp;
- temp->next = p;
- linehead->NodeNum++;
- //return TRUE;
- }
- //调用者保障local小于linehead->NodeNum
- LineNode *GetNode(LineHead *linehead, int local)
- {
- LineNode *p;
- int i;
- //改为断言
- //######################
- if (NULL == linehead)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[LINEISNULL]);
- //return NULL;
- exit(0);
- }
- //######################
- //改为断言
- //######################
- if (local >= linehead->NodeNum)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[LOCALUPNODENUM]);
- //return NULL;
- exit(0);
- }
- //######################
- p = linehead->head;
- for (i = 0; i < local; i++)
- {
- p = p->next;
- }
- if (p == linehead->head)
- {
- linehead->head = p->next;
- if (NULL != p->next)
- {
- p->next->prep = NULL;
- }
- }
- else
- {
- p->prep->next = p->next;
- if (NULL != p->next)
- {
- p->next->prep = p->prep;
- }
- }
- linehead->NodeNum--;
- //保障传出参数使用不会出现越权访问
- p->next = p->prep = NULL;
- return p;
- }
- //调用者保障local小于linehead->NodeNum
- int GetNodeData(LineHead *linehead, int local)
- {
- LineNode *p;
- int i;
- //改为断言
- //######################
- if (NULL == linehead)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[LINEISNULL]);
- //return NULL;
- exit(0);
- }
- //######################
- //改为断言
- //######################
- if (local >= linehead->NodeNum)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[LOCALUPNODENUM]);
- //return ERROR;
- exit(0);
- }
- //######################
- p = linehead->head;
- for (i = 0; i < local; i++)
- {
- p = p->next;
- }
- return p->data;
- }
- /*
- int ListForEach(LineHead *linehead, Callbcak visit, void *ctx)
- {
- int ret = HEAD;
- ListNode *iter;
- iter = linehead->head;
- while ((NULL != iter) && ((linehead->NodeNum - 1) != ret))
- {
- ret = visit(ctx, iter->data);
- iter = iter->next;
- }
- return ret;
- }
- */
- void ShowLine(LineHead *linehead)
- {
- LineNode *p;
- //改为断言
- //######################
- if (NULL == linehead)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[LINEISNULL]);
- //return NULL;
- exit(0);
- }
- //######################
- p = linehead->head;
- printf("\nLine:\n");
- printf("##############################\n");
- while (NULL != p)
- {
- printf("%d ", p->data);
- p = p->next;
- }
- printf("\n##############################\n");
- }
动态数组:
DArray.h
- #ifdef _cplusplus
- extern "C" {
- #endif
- #define OK 0
- #define FAIL 1
- #define ERRNUM 6
- #define MEMORYEMPTY 0
- #define NODARRAY 1
- #define NODATATOSORT 2
- #define FUNCISNULL 3
- #define SORTFUNCISNULL 4
- struct _darray;
- typedef struct _darray DArray;
- typedef int (*DataCompareFunc)(int data1, int data2);
- typedef int (*SortFunc)(int *array, int size, DataCompareFunc cmp);
- DArray *DArray_Create();
- void DArray_Destory(DArray *darray);
- //插入在local前,当local大于数组size时插入在最后
- int DArray_Insert(DArray *darray, int data, int local);
- int DArray_Delete(DArray *darray, int local);
- int DArray_GetData(DArray *darray, int local);
- int DArray_SetData(DArray *darray, int data, int local);
- int DArray_Length(DArray *darray);
- //int DArray_Find(DArray *darray, CallBack compare, void *ctx);
- void DArray_Show(DArray *darray);
- /* 提供排序函数供调用者参考
- //通过回调函数实现升序或是降序排列,比较函数由调用者实现
- int Bubble_Sort(int *array, int size, DataCompareFunc cmp);
- int Quick_Sort(int *array, int size, DataCompareFunc cmp);
- int Merge_Sort(int *array, int size, DataCompareFunc cmp);
- */
- //提供动态数组排序接口函数,排序、比较函数都由调用者实现
- int DArray_Sort(DArray *darray, SortFunc sort, DataCompareFunc cmp);
- #ifdef _cplusplus
- }
- #endif
DArray.c
- #include <stdio.h>
- #include <stdlib.h>
- #include "Darray.h"
- #define MIN_PRE_ALLOCATE_NR 10
- struct _darray {
- int *data;
- int size;
- int alloc_size;
- };
- char *errorstring[ERRNUM] = {"Memory can't be alloced!", "The darray has not created!",
- "There is no data to sort!", "The compare function is null!",
- "The sort function is null!"};
- static int DArray_Expend(DArray *darray, int need)
- {
- int *data;
- int alloc_size;
- //改为断言
- //######################
- if (NULL == darray)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[NODARRAY]);
- //return NULL;
- exit(0);
- }
- //######################
- if ((darray->size + need) > darray->alloc_size)
- {
- //避免darray->alloc_size为0的情况在分配1.5倍的空间基础上加上一个10
- alloc_size = darray->alloc_size + (darray->alloc_size >> 1) + MIN_PRE_ALLOCATE_NR;
- data = (int *)realloc(darray->data, sizeof(int) * darray->alloc_size);
- if (NULL == data)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[MEMORYEMPTY]);
- exit(0);
- }
- darray->data = data;
- darray->alloc_size = alloc_size;
- }
- return ((darray->size + need) <= darray->alloc_size) ? OK : FAIL;
- }
- DArray *DArray_Create()
- {
- DArray *darray;
- darray = (DArray *)malloc(sizeof(DArray));
- if (NULL == darray)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[MEMORYEMPTY]);
- exit(0);
- }
- darray->data = NULL;
- darray->alloc_size = darray->size = 0;
- return darray;
- }
- void DArray_Destory(DArray *darray)
- {
- //改为断言
- //######################
- if (NULL == darray)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[NODARRAY]);
- //return NULL;
- exit(0);
- }
- //######################
- if (NULL != darray->data)
- {
- free(darray->data);
- }
- free(darray);
- }
- //插入在local前,当local大于数组size时插入在最后
- int DArray_Insert(DArray *darray, int data, int local)
- {
- int cursor;
- int i;
- //改为断言
- //######################
- if (NULL == darray)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[NODARRAY]);
- //return NULL;
- exit(0);
- }
- //######################
- cursor = (local < darray->size) ? local : darray->size;
- if (OK == DArray_Expend(darray, 1))
- {
- for (i = darray->size; i > cursor; i--)
- {
- darray->data[i] = darray->data[i-1];
- }
- darray->data[cursor] = data;
- darray->size++;
- }
- return OK;
- }
- //当数组的元素个数小于分配空间的一半时进行重新分配空间
- static int DArray_Shrink(DArray *darray)
- {
- int *data;
- int alloc_size;
- //改为断言
- //######################
- if (NULL == darray)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[NODARRAY]);
- //return NULL;
- exit(0);
- }
- //######################
- //当数组已分配空间小于最小限额值时不做重新分配
- if ((darray->size < (darray->alloc_size >> 1)) &&
- (darray->alloc_size > MIN_PRE_ALLOCATE_NR))
- {
- alloc_size = darray->size + (darray->size >> 1);
- data = (int *)realloc(darray->data, sizeof(int) * alloc_size);
- if (NULL != data)
- {
- darray->data = data;
- darray->alloc_size = alloc_size;
- }
- }
- return OK;
- }
- int DArray_Delete(DArray *darray, int local)
- {
- int i;
- //改为断言
- //######################
- if (NULL == darray)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[NODARRAY]);
- //return NULL;
- exit(0);
- }
- //######################
- if (local >= darray->size)
- {
- printf("\nWrong location!\n");
- return FAIL;
- }
- for (i = local; i < (darray->size - 1); i++)
- {
- darray->data[i] = darray->data[i+1];
- }
- darray->size--;
- DArray_Shrink(darray);
- return OK;
- }
- int DArray_GetData(DArray *darray, int local)
- {
- int data;
- //改为断言
- //######################
- if (NULL == darray)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[NODARRAY]);
- //return NULL;
- exit(0);
- }
- //######################
- if (local >= darray->size)
- {
- printf("\nWrong location!\n");
- return FAIL;
- }
- data = darray->data[local];
- return data;
- }
- int DArray_SetData(DArray *darray, int data, int local)
- {
- //改为断言
- //######################
- if (NULL == darray)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[NODARRAY]);
- //return NULL;
- exit(0);
- }
- //######################
- if (local >= darray->size)
- {
- printf("\nWrong location!\n");
- return FAIL;
- }
- darray->data[local] = data;
- return OK;
- }
- int DArray_Length(DArray *darray)
- {
- //改为断言
- //######################
- if (NULL == darray)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[NODARRAY]);
- //return NULL;
- exit(0);
- }
- //######################
- return darray->size;
- }
- //int DArray_Find(DArray *darray, CallBack compare, void *ctx);
- void DArray_Show(DArray *darray)
- {
- int i;
- //改为断言
- //######################
- if (NULL == darray)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[NODARRAY]);
- //return NULL;
- exit(0);
- }
- //######################
- printf("\nDArray:\n");
- printf("##############################\n");
- for (i = 0; i < darray->size; i++)
- {
- printf("%d ", darray->data[i]);
- }
- printf("\n##############################\n");
- }
- //下面两个排序函数只是给调用者参考
- /* 升序排列
- static int int_cmp(int a, int b)
- {
- return a - b;
- }
- */
- /* 降序排列
- static int int_cmp_invert(int a, int b)
- {
- return b - a;
- }
- */
- //冒泡排序,最简单实用的
- //通过回调函数实现升序或是降序排列,比较函数由调用者实现
- int Bubble_Sort(int *array, int size, DataCompareFunc cmp)
- {
- int i, j, k;
- int data;
- if (NULL == array)
- {
- printf("\nERROR : %s\n", errorstring[NODATATOSORT]);
- return FAIL;
- }
- if (size < 2)
- {
- return OK;
- }
- for (k = size - 1; k > 0; k--)
- {
- for (i = 1, j = 0; i < k; i++)
- {
- if (cmp(array[i], array[j]) > 0)
- {
- j = i;
- }
- }
- if (cmp(array[j], array[k]) > 0)
- {
- data = array[k];
- array[k] = array[j];
- array[j] = data;
- }
- }
- return OK;
- }
- //快排,当所有数据都可以放在内存中最快速实用的
- static void quick_sort_impl(int *array, int left, int right, DataCompareFunc cmp)
- {
- int save_left = left;
- int save_right = right;
- int x = array[left];
- //将小于x的值放在左边,大于x的值放右边
- while (left < right)
- {
- while ((cmp(array[right], x) >= 0) && (left < right))
- {
- right--;
- }
- if (left != right)
- {
- array[left] = array[right];
- left++;
- }
- while ((cmp(array[left], x) <= 0) && (left < right))
- {
- left++;
- }
- if (left != right)
- {
- array[right] = array[left];
- right--;
- }
- }
- array[left] = x;
- //对左半部分排序
- if (save_left < left)
- {
- quick_sort_impl(array, save_left, left-1, cmp);
- }
- //对右半部分排序
- if (save_right > left)
- {
- quick_sort_impl(array, left+1, save_right, cmp);
- }
- //return;
- }
- int Quick_Sort(int *array, int size, DataCompareFunc cmp)
- {
- if (NULL == array)
- {
- printf("\nERROR : %s\n", errorstring[NODATATOSORT]);
- return FAIL;
- }
- if (NULL == cmp)
- {
- printf("\nERROR : %s\n", errorstring[FUNCISNULL]);
- return FAIL;
- }
- if (size > 1)
- {
- quick_sort_impl(array, 0, size-1, cmp);
- }
- return OK;
- }
- //二路归并排序,当数据无法一次性放在内存中时最好的
- static void merge_sort_impl(int *storage, int *array,
- int low, int mid, int high,
- DataCompareFunc cmp)
- {
- int x;
- int i = low;
- int j = mid;
- int k = high;
- //对左半部分排序
- if ((low + 1) < mid)
- {
- x = low + ((mid - low) >> 1);
- merge_sort_impl(storage, array, low, x, mid, cmp);
- }
- //对右半部分排序
- if ((mid + 1) < high)
- {
- x = mid + ((high - mid) >> 1);
- merge_sort_impl(storage, array, mid, x, high, cmp);
- }
- //合并两个有序数组
- while ((j < mid) && (k < high))
- {
- if (cmp(array[j], array[k]) <= 0)
- {
- storage[i++] = array[j++];
- }
- else
- {
- storage[i++] = array[k++];
- }
- }
- while (j < mid)
- {
- storage[i++] = array[j++];
- }
- while (k < high)
- {
- storage[i++] = array[k++];
- }
- for (i = low; i < high; i++)
- {
- array[i] = storage[i];
- }
- }
- int Merge_Sort(int *array, int size, DataCompareFunc cmp)
- {
- int *storage = NULL;
- if (NULL == array)
- {
- printf("\nERROR : %s\n", errorstring[NODATATOSORT]);
- return FAIL;
- }
- if (NULL == cmp)
- {
- printf("\nERROR : %s\n", errorstring[FUNCISNULL]);
- return FAIL;
- }
- if (size > 1)
- {
- storage = (int *)malloc(sizeof(int) * size);
- if (NULL != storage)
- {
- merge_sort_impl(storage, array, 0, size>>1, size, cmp);
- free(storage);
- }
- }
- return OK;
- }
- //排序接口
- int DArray_Sort(DArray *darray, SortFunc sort, DataCompareFunc cmp)
- {
- //改为断言
- //######################
- if (NULL == darray)
- {
- printf("\n%s %d\nERROR : %s\n", __FILE__, __LINE__, errorstring[NODARRAY]);
- //return NULL;
- exit(0);
- }
- //######################
- if (NULL == sort)
- {
- printf("\nERROR : %s\n", errorstring[SORTFUNCISNULL]);
- return FAIL;
- }
- if (NULL == cmp)
- {
- printf("\nERROR : %s\n", errorstring[FUNCISNULL]);
- return FAIL;
- }
- sort(darray->data, darray->size, cmp);
- return OK;
- }
写的仓促,没有仔细推敲,经不起考验~~呵呵!就当是有个念想吧~~大家凑合着看吧!