双向链表

链表练习,c实现,简单封装。

"myList.h"

#ifndef _MY_LIST_H_
#define _MY_LIST_H_

typedef struct ListNodeTag{
	void *data;

	struct ListNodeTag *prev;
	struct ListNodeTag *next;
}ListNode, *pListNode;

//NodeCmpfun(s1, s2), s1==s2, return 0; s1>s2, ruturn 1; s1<s2, return -1;
typedef int (*NodeCmpFun)(void *, void *);
typedef void (*ShowDataFun)(void *);

typedef struct ListTag{
	int (*push_front)(struct ListTag*, void *data, size_t);
	int (*push_back)(struct ListTag*, void *data, size_t);
	int (*push)(struct ListTag*, int pos, void *data, size_t);
	
	int (*pop_front)(struct ListTag*);
	int (*pop_back)(struct ListTag*);
	int (*pop)(struct ListTag*, int pos);

	pListNode (*find)(struct ListTag*, void *data, size_t);

	pListNode (*begin)(struct ListTag*);
	pListNode (*end)(struct ListTag*);
	int (*size)(struct ListTag*);

	void (*show_list)(struct ListTag*);

	//private data, do not modify them directly !!
	pListNode head;
	pListNode tail;
	NodeCmpFun cmpFun;
	ShowDataFun show;
	int num; //number of list member
	int sz;  //size of data in the node
}List, *pList;

pList ListCreate(int datasize, NodeCmpFun cmpFun, ShowDataFun show);
int ListDelete(pList);

#endif /*_MY_LIST_H_*/

 

"myList.c"

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

#include "myList.h"

//#define NDEBUG       //This one should be in front of #include <assert.h> if define NDEBUG
#include <assert.h>

static pListNode List_NewNode(void *data, size_t sz)
{
	pListNode n = (pListNode)malloc(sizeof(ListNode));
	if(n == NULL){
		perror("malloc");
		return NULL;
	}

	n->data = malloc(sz);
	if(n->data == NULL){
		perror("malloc");
		free(n);
		return NULL;
	}

	memcpy(n->data, data, sz);
	n->prev = NULL;
	n->next = NULL;

	return n;
}

static int List_Push(pList l, int pos, void *data, size_t sz)
{
	assert( l != NULL);
	assert(data != NULL);
	assert(sz == l->sz);
	assert(pos >= 0 && pos <= l->num);

	pListNode iter = l->head;
	pListNode tmp;
	int idx;

	if(pos<0 || pos>l->num)
		return -1;

	pListNode n = List_NewNode(data, sz);
	if(n == NULL)
		return -2;

	//no list member, new node to be head and tail
	if(l->num == 0){
		l->head = n;
		l->tail = n;
		l->num++;
		return 0;
	}

	//insert the front
	if(pos == 0){
		n->next = l->head;
		n->prev = NULL;
		l->head->prev = n;

		l->head = n;
	}else{
		//insert the tail
		if(pos == l->num)
		{
			n->next = NULL;
			n->prev = l->tail;
			l->tail->next = n;

			l->tail = n;
		}
		else
		{
			for(idx=0; idx<pos-1; idx++)
				iter = iter->next;

			tmp = iter->next;
			iter->next = n;
			n->next = tmp;
			n->prev = iter;
			tmp->prev = n;
		}
	}

	l->num++;

	return 0;
}

static int List_PushFront(pList l, void *data, size_t sz)
{
	return List_Push(l, 0, data, sz);
}

static int List_PushBack(pList l, void *data, size_t sz)
{
	return List_Push(l, l->num, data, sz); 
}

static int List_Pop(pList l, int pos)
{
	assert( l != NULL);
	assert( pos >0 && pos <= l->num);

	pListNode tmp;
	pListNode iter = l->head;
	int idx;
	for(idx=1; idx<pos; idx++)
		iter = iter->next;

	//move the front
	if(iter == l->head){
		if(l->num == 1){
			assert( l->head == l->tail);
			
			free(l->head->data);
			free(l->head);
			l->head = NULL;
			l->tail = NULL;
		}else{
			tmp= l->head;
			l->head = l->head->next;
			l->head->prev = NULL;

			tmp->next = NULL;
			tmp->prev = NULL;
			
			free(tmp->data);
			free(tmp);
		}
	}

	//move the tail
	else if(iter == l->tail)
	{
		tmp = l->tail;
		if(l->num == 1){
			assert(l->tail == l->head);
			
			free(l->tail->data);
			free(l->tail);
			l->tail = l->head = NULL;
		}else{
			l->tail = l->tail->prev;
			l->tail->next = NULL;

			tmp->prev = tmp->next = NULL;
			free(tmp->data);
			free(tmp);
		}
	}
	//move the middle one
	else
	{
		iter->prev->next = iter->next;
		iter->next->prev = iter->prev;

		iter->next = iter->prev = NULL;
		free(iter->data);
		free(iter);
	}

	l->num--;

	return 0;
}

static int List_PopFront(pList l)
{
	return List_Pop(l, 1);
}

static int List_PopBack(pList l)
{
	return List_Pop(l, l->num);	
}

static void List_Show(pList l)
{
	if( l == NULL )
		return;

	printf("list, total member: %d\n", l->num);
	pListNode iter = l->head;
	if(l->show != NULL)
	{
		while(iter != NULL)
		{
			l->show(iter->data);
			iter = iter->next;
		}
	}
	printf("\n");
}

static pListNode List_Find(pList l, void *data, size_t sz)
{
	assert(l != NULL && data != NULL && sz == l->sz);

	if(l->cmpFun == NULL)
		return -1;

	pListNode iter = l->head;
	while(iter != NULL)
	{
		if(l->cmpFun(data, iter->data) == 0){
			break;
		}
		
		iter = iter->next;
	}

	return iter;
}

pListNode List_Begin(pList l)
{
	assert(l != NULL);
	return l->head;
}

pListNode List_End(pList l)
{
	assert(l != NULL);
	return l->tail;
}

int List_Size(pList l)
{
	assert(l != NULL);
	return l->num;
}


pList ListCreate(int datasize, NodeCmpFun cmpFun, ShowDataFun show)
{
	pList this = (pList)malloc(sizeof(List));
	if(this == NULL){
		perror("malloc\n");
		return NULL;
	}

	//private data
	this->head = NULL;
	this->tail = NULL;
	this->num = 0;
	this->sz = datasize;
	this->cmpFun = cmpFun;
	this->show = show;

	//operation
	this->push = List_Push;
	this->push_front = List_PushFront;
	this->push_back = List_PushBack;

	this->pop = List_Pop;
	this->pop_front = List_PopFront;
	this->pop_back = List_PopBack;

	this->find = List_Find;
	this->show_list = List_Show;
	this->begin = List_Begin;
	this->end = List_End;
	this->size = List_Size;
}

int ListDelete(pList l)
{
	assert(l != NULL);

	pListNode iter = l->head;
	while(iter != NULL)
	{
		l->pop_front(l);
		iter = l->head;
	}

	assert(l->num == 0);
	free(l); l = NULL;

	return 0;
}

 

"main.c"

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

void ShowData(void *data)
{
	if(data == NULL)
		return;
	
	int *p = (int *)data;
	printf("%d\n", *p);
}

int IntCmpFun(void *s1, void *s2)
{
	int *p1 = (int *)s1;
	int *p2 = (int *)s2;

	if(*p1 == *p2){
		return 0;
	}else if(*p1 > *p2){
		return 1;
	}else{
		return -1;
	}
}

int main()
{
	int data[] = {1, 2, 3, 4, 5, 6, 7, 8};
	int num = sizeof(data)/sizeof(int);
	int idx;
	int tmp;
	
	pList l = ListCreate(sizeof(int), IntCmpFun, ShowData);
	if(l == NULL)
		exit(-1);

	for(idx=0; idx<num; idx++)
		l->push_front(l, data+idx, sizeof(int));

	l->show_list(l);

	for(idx=4; idx<num; idx++)
		l->push_back(l, data+idx, sizeof(int));

	l->show_list(l);

	for(idx=0; idx<num-4; idx++)
		l->push_front(l, data+idx, sizeof(int));

	l->show_list(l);

	l->pop_back(l);
	l->show_list(l);

	l->pop_front(l);
	l->show_list(l);

	pListNode iter_b = l->begin(l);
	ShowData(iter_b->data);
	pListNode iter_e = l->end(l);
	ShowData(iter_e->data);

	tmp = 88;
	l->push(l, 14, &tmp, sizeof(tmp));
	tmp = 99;
	l->push(l, 14, &tmp, sizeof(tmp));
	l->show_list(l);

	l->pop(l, 15);
	l->show_list(l);

    tmp = 98;
	pListNode iter_f = l->find(l, &tmp, sizeof(int));
	if(iter_f == NULL){
		printf("%d not found!\n", tmp);
	}else{
		printf("found %d\n", *(int *)iter_f->data);
	}

	ListDelete(l);

	return 0;
}

 

转载于:https://my.oschina.net/u/1252361/blog/155851

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值