链表组件化分为三个步骤:
第一步:规划函数功能;
第二步:对函数功能进行定义实现;
第三步:对函数进行测试驱动;
编写链表功能组件化首先应在Visual-Studio中创建链表组件化项目,在头文件处创建linkedlist.h和collections.h文件,在源文件中创建Collections.cpp和LinkedList.cpp功能文件与三个测试文件。
在头文件 linkedlist.h中定义链表的添加、删除、清空、修改、按下标查找、按数据查找、栈实现、队列实现等功能,在collections.h中定义链表的排序、交换、打乱、最大最小值等功能。
下面我们先编写 linkedist.h文件中的函数功能,如图所示:
1./*创建链表*/
PLinkedList createLinkedList();
PLinkedList createLinkedList()
{
PLinkedList newList = (PLinkedList)malloc(sizeof(LinkedList));
if (newList!=NULL)
{
newList->header = NULL;
newList->ender = NULL;
newList->size = 0;
newList->nextNode = NULL;
}
return newList;
}
2./*创建节点*/
PNode createNode( void * data);
PNode createNode(void* data)
{
PNode newnode = (PNode)malloc(sizeof(Node));
newnode->prev = NULL;
newnode->next = NULL;
newnode->data = data;
return newnode;
}
3./*增加新的节点*/
void add(PLinkedList list , void * data);
void add(PLinkedList list, void* data)
{
PNode newNode=createNode(data);
if (list->size==0)//空链表
{
list->header = list->ender = newNode;
}
else
{
list->ender->next = newNode;
newNode->prev = list->ender;
list->ender = newNode;
}
list->size++;
}
4./*在某节点的位置上插入新节点*/
void insert(PLinkedList list ,int index, void * data);
void insert(PLinkedList list, int index, void* data)
{//空链表 //插入尾部
if (list->size==0 || index>=list->size)
{
add(list, data);
return;
}
PNode newnode = createNode(data);
//插入到头部
if (index<=0)//健壮性/鲁棒性
{
newnode->next = list->header;
list->header->prev = newnode;
list->header = newnode;
}
else
{
//理想的 中间插入
PNode p = findNode(list, index);
PNode q = p->prev;//插入点的前面的节点
newnode->next = p;
p->prev = newnode;
q->next = newnode;
newnode->prev = q;
}
list->size++;
}
5./*删除 指定 下标的节点*/
void* removeIndex(PLinkedList list ,int index);
void* removeIndex(PLinkedList list, int index)
{
if (list->size==0)
{
return NULL;
}
PNode p =NULL;//p指向被删除的节点
if (list->size==1)//唯一节点时的处理
{
p = list->header;
list->header = list->ender = NULL;
}
else if (index<=0)//删除头节点
{
p = list->header;
list->header = p->next;
list->header->prev = NULL;
}
else if (index>=list->size-1)//删除尾部节点
{
p = list->ender;
list->ender = p->prev;
list->ender->next = NULL;
}
else
{
//理想的 中间删除
p = findNode(list, index);
PNode q = p->prev;
PNode m = p->next;
q->next = m;
m->prev = q;
}
//保护被删节点内的数据
if (p!=NULL)
{
void* temp = p->data;
free(p);
list->size--;
return temp;
}
return NULL;
}
6./*删除等于参数的首个节点*/
void removeData(PLinkedList list , void* data, Compare fun);
这里函数中有函数参数,这里是比较函数,定义两个void*类型的参数在定义的函数内转换要比较类型,然后比较;具如图所示:
在主函数测试函数中加入比较函数即可;
void removeData(PLinkedList list, void* data, Compare fun)
{
int i=indexOf(list, data,fun);
if (i>=0)
{
removeIndex(list, i);
}
}
7./*某下标对应的 节点*/
void* get(PLinkedList list ,int index);
void* get(PLinkedList list, int index)
{
PNode p = findNode(list, index);
return p!=NULL? p->data : NULL;
}
8./*找到节点*/
PNode findNode(PLinkedList list ,int index);
PNode findNode(PLinkedList list, int index)
{
PNode p = list->header;
for (int i = 0; i < index; i++)
{
p = p->next;
}
return p;
}
9./*某下标对应的 节点数据进行更新 */
void set(PLinkedList list ,int index, void* newdata);
void set(PLinkedList list, int index, void* newdata)
{
PNode p=findNode(list, index);
if ( p!=NULL)
{
p->data = newdata;
}
}
10./*某数据对应的下标*/
int indexOf(PLinkedList list , void* data,Compare fun );
int indexOf(PLinkedList list, void* data, Compare fun)
{
iterator(list);
for (int i=0 ;hasNext(list) ;i++ )
{
//if ( next(list)== data)
if ( fun(next(list), data)==0 )
{
return i;
}
}
return -1;
}
11./*节点数量*/
int size(PLinkedList list );
int size(PLinkedList list)
{
return list->size;
}
12./*清空链表*/
void clear(PLinkedList list );
void clear(PLinkedList list)
{
PNode p = list->header;
PNode q = NULL;
while (p!=NULL)
{
q = p;
p = p->next;
free(q);
}
list->header = list->ender = NULL;
list->size = 0;
}
13.迭代器
//产生新的迭代器
void iterator(PLinkedList list);
//是否有下一个节点
int hasNext(PLinkedList list);
//取得下一个节点数据
void* next(PLinkedList list);
void iterator(PLinkedList list)
{
list->nextNode = list->header;
}
int hasNext(PLinkedList list)
{
return list->nextNode!= NULL;
}
void* next(PLinkedList list)
{
if (list->nextNode!=NULL)
{
void* data = list->nextNode->data;
//为下一次做准备
list->nextNode = list->nextNode->next;
return data;
}
return NULL;
}
14.实现栈stack功能,满足LIFO原则:后入先出;
/* 入栈*/
void push(PLinkedList list , void* data);
/*出栈*/
void* pop(PLinkedList list );
void push(PLinkedList list, void* data)
{
add(list, data);
}
void* pop(PLinkedList list)
{
return removeIndex(list,size(list)-1);
}
15.实现队列queue功能,满足FIFO原则:先进先出;
void addFirst(PLinkedList list , void* data);
void addLast(PLinkedList list , void* data);
void* removeFirst(PLinkedList list );
void* removeLast(PLinkedList list );
void addFirst(PLinkedList list, void* data)
{
insert(list, 0, data);
}
void addLast(PLinkedList list, void* data)
{
add(list, data);
}
void* removeFirst(PLinkedList list)
{
return removeIndex(list,0);
}
void* removeLast(PLinkedList list)
{
return removeIndex(list, size(list)-1);
}
然后编写collections.h文件的函数功能,如图所示:
1./*将链表2 追加到链表1的后面*/
void addAll__(PLinkedList list1, PLinkedList list2);
void addAll__(PLinkedList list1, PLinkedList list2)
{
iterator(list2);
while (hasNext(list2))
{
add(list1, next(list2));
}
}
2./*返回最大数据域*/
void* max__(PLinkedList list,Compare fun);
void* max__(PLinkedList list, Compare fun)
{
if (list->size == 0)return NULL;
void* maxValue = list->header->data;
iterator(list);
while (hasNext(list))
{
void* data =next(list);
if ( fun(maxValue,data)<0 )
{
maxValue = data;
}
}
return maxValue;
}
3./*返回最小数据域*/
void* min__(PLinkedList list,Compare fun);
void* min__(PLinkedList list, Compare fun)
{
if (list->size == 0)return NULL;
void* min_value = get(list, 0);
for (int i=1 ;i<size(list) ;i++ )
{
void* data = get(list, i);
if ( fun(min_value, data)>0)
{
min_value = data;
}
}
return min_value;
}
4./*交换 两个下标对应的数据域*/
void swap__(PLinkedList list, int i, int j);
void swap__(PLinkedList list, int i, int j)
{
PNode pi = findNode(list, i);
PNode pj = findNode(list, j);
void* t;
t = pi->data;
pi->data = pj->data;
pj->data = t;
}
5./*对链表 按 Compare比较规则 进行排序 */
void sort__(PLinkedList list,Compare fun );
void sort__(PLinkedList list, Compare fun)
{
//for (int suo=0 ; suo<size(list)-1; suo++)
//{
// for (int bi = suo+1; bi < size(list); bi++)
// {
// if ( fun(get(list,suo) ,get(list,bi) )> 0 )
// {
// swap__(list, suo, bi);
// }
// }
//}
PNode p_suo = list->header;
PNode p_bi =NULL;
for (int suo = 0; suo < size(list) - 1; suo++)
{
p_bi = p_suo->next;
for (int bi = suo + 1; bi < size(list); bi++)
{
if( fun(p_suo->data,p_bi->data)>0)
{
void* t;
t = p_suo->data;
p_suo->data = p_bi->data;
p_bi->data = t;
}
p_bi = p_bi->next;
}
p_suo = p_suo->next;
}
}
6./*使用折半查找思路 查询某key数据的下标*/
int binarySearch__(PLinkedList list, void * key, Compare fun);
int binarySearch__(PLinkedList list, void* key, Compare fun)
{
int low = 0;
int high = size(list) - 1;
int mid;
do
{
mid = (low + high) / 2;
void* data = get(list, mid);
int r = fun(data, key);
if (r==0)
{
return mid;
}
else if (r<0) {
low = mid + 1;
}
else
{
high = mid - 1;
}
} while (low<=high);
return -1;
}
7./*打乱链表的顺序*/
void shuffle__(PLinkedList list);
void shuffle__(PLinkedList list)
{
srand((unsigned) time(NULL));
for (int i=0 ;i<size(list) ;i++ )
{
int a = rand() % size(list);
int b = rand() % size(list);
swap__(list, a, b);
}
}
8./*对链表成员进行首尾倒置*/
void reverse__(PLinkedList list);
void reverse__(PLinkedList list)
{
//for (int i=0,j=size(list)-1 ; i<j; i++,j--)
//{
// swap__(list, i, j);
//}
PNode p = list->header;
PNode q = list->ender;
void* t;
for (int i = 0, j = size(list) - 1; i < j; i++, j--)
{
t = p->data;
p->data = q->data;
q->data = t;
p = p->next;
q = q->prev;
}
}
9.*把复合fun比较规则的数据域 替换成新的数据域*/
void replaceAll__(PLinkedList list, void *oldVal, void *newVal, Compare fun );
void replaceAll__(PLinkedList list, void* oldVal, void* newVal, Compare fun)
{
PNode p = list->header;
while (p!=NULL)
{
if (fun(p->data,oldVal)==0)
{
p->data = newVal;
}
p = p->next;
}
}
编写完基本程序检查无误后,打开V-S软件创建新项目选择静态库,名字为StaticListLib;
找到之前编辑的链表功能的文件夹将.p与.cpp功能文件复制,然后右击StaticListLib文件点击添加—>现有项将复制的文件粘贴里然后点击添加;如图所示:
然后再下面两个文件的第一行加 #include"pch.h";如图所示:
然后一般选择在x86系统下点击生成选择生成StaticListLib(U);
生成完成后,后在窗口显示生成位置;
将生成的静态库.lib文件复制到刚才的.cpp与.h文件中,将.lib与.h文件复制到新建的测试文件中即可使用;如图所示:
最后在主函数头部添加#pragma comment(lib,".\\StaticListLib.lib"),然后main函数中调用功能函数即可。