一、概念
双向链表概念
( double linked List) 是在单链表的每个结点中,再设置一个指向其前驱结点的指针域。所以在双向链表中的结点都有两个指针域, 一个指向直接后继,另一个指向直接前驱。
二、双向不循环链表
2.1 定义数据类型
typedef void * datatype;
typedef struct list_s
{
struct list_s *prev; //指向直接前驱
datatype data; //数据域
struct list_s *next; //指向直接后驱
}list_t;
2.2 生成头节点
list_t *create_list(void) //新建双向链表
{
list_t *list = NULL;
list = malloc(sizeof(*list));
list->data = NULL;
list->prev = NULL;
list->next = NULL;
return list;
}
2.3 插入节点
2.3.1 头/尾插
enum
{
HEADLIST,
TRAILLIST
};
int insert_list (list_t *head,const datatype data,int datasize,int mode) //头插、尾插数据
{
list_t *new = NULL;
list_t *q = NULL;
new = malloc( sizeof(*new) );
new->data = malloc(sizeof(datasize));
new->prev = NULL;
new->next = NULL;
memcpy(new->data,data,datasize);
switch(mode) {
case HEADLIST:
new->next=head->next;
new->prev=head;
head->next->prev = new; //必须保证至少有一个数据节点
head->next=new;
break;
case TRAILLIST:
for (q = head; q->next != NULL; q = q->next);
q->next = new;
new->prev = q;
break;
default:
free(new->data);
free(new);
return -1;
}
return 0;
}
2.3.2 选择插
int insert_select_list (list_t *head, int num, datatype data) //选择插
{
int i;
list_t *q = NULL;
list_t *new = NULL;
if (doulist_length (head) < num || num <= 1) {
printf ("insert_select_list num is erorr!\n");
return -1;
}
new = malloc( sizeof(*new) );
new->data = malloc(sizeof (int));
new->prev = NULL;
new->next = NULL;
memcpy(new->data,data,sizeof(int));
for (i = 1, q = head; q->next != NULL; i++, q = q->next) {
if (i == num) {
new->next = q->next;
new->prev = q;
new->next->prev = new;
q->next = new;
return 0;
}
}
return -1;
}
2.4 打印
int display_list (list_t *head) //打印链表
{
list_t *list;
printf ("head : %p <--> ",head);
for(list = head->next; list != NULL ; list = list->next) {
printf(" %d - %p < -- > ",*((int *)(list->data)), list);
}
printf ("\n");
return 0;
}
2.5 判空
int isempty_list (list_t *head) //判空
{
return head->next == NULL ? 1 : 0;
}
2.6 返回链表长度
int doulist_length (list_t *head) //返回链表长度
{
int i;
list_t *q = NULL;
for (i = 0, q = head; q->next != NULL; q = q->next, i++);
return i;
}
2.7 删除链表某个节点
int delete_list(list_t *head, const datatype data, int datasize) //删除链表某个节点
{
list_t *q = NULL;
if(isempty_list(head))
return -1;
for(q = head->next; q != NULL; q = q->next) {
if(!memcmp(q->data,data,datasize)) {
q->prev->next=q->next;
q->next->prev=q->prev;
free (q->data);
return -1;
}
}
return 0;
}
2.8 排序
int func_order(void *s1, void *s2) //作为函数指针,顺序
{
return *((int *)s1) - *((int *)s2);
}
int func_invert(void *s1, void *s2) //作为函数指针,反序
{
return *((int *)s2) - *((int *)s1);
}
int sort_list(list_t *head,int (*sort)(void *,void *)) //排序
{
list_t *p;
int i, num, length;
length = doulist_length (head);
for(i = 0; i < length - 1; i++) {
num = length - i - 1;
for(p = head->next; num > 0; p = p->next, num--)
{
if(sort(p->data, p->next->data) > 0) {
void *tmp = p->data;
p->data = p->next->data;
p->next->data = tmp;
}
}
}
return 0;
}
2.9 查找某个数据
int find_list(list_t *head,const datatype data,int datasize) //查找某个数据
{
list_t *q = NULL;
for(q = head->next; q != NULL; q = q->next) {
if( !memcmp (q->data,data,datasize) ) {
printf ("find data: %d\n",*((int *)(q->data)));
return 0;
}
}
return -1;
}
2.10 销毁链表
void destory_list (list_t *head) //销毁链表
{
list_t *q = NULL;
for(q = head->next->next; q != NULL; q = q->next) {
free(q->prev->data);
free(q->prev);
}
free(head->data);
free(head);
}
2.11 测试
int main(void)
{
list_t *list = NULL;
int data[10] = {8, 10, 7, 1, 6, 4, 9, 2, 3, 5};
list = create_list ();
if (isempty_list (list) ) {
printf ("doulist is null !\n");
}
insert_list (list, &data[0], sizeof (int), TRAILLIST);
insert_list (list, &data[1], sizeof (int), TRAILLIST);
insert_list (list, &data[2], sizeof (int), TRAILLIST);
insert_list (list, &data[3], sizeof (int), TRAILLIST);
printf ("tail insert, doulist length is : %d\n",doulist_length(list));
display_list (list);
insert_list (list, &data[4], sizeof (int), HEADLIST);
insert_list (list, &data[5], sizeof (int), HEADLIST);
insert_list (list, &data[6], sizeof (int), HEADLIST);
insert_list (list, &data[7], sizeof (int), HEADLIST);
printf ("head insert, doulist length is : %d\n",doulist_length(list));
display_list (list);
insert_select_list (list, 2, &data[8]);
insert_select_list (list, 2, &data[9]);
printf ("select insert, doulist length is : %d\n",doulist_length(list));
display_list (list);
delete_list(list, &data[1], sizeof (int));
printf ("delete data: 10, doulist length is : %d\n",doulist_length(list));
display_list (list);
sort_list (list, func_order);
printf ("order sort data, doulist length is : %d\n",doulist_length(list));
display_list (list);
sort_list (list, func_invert);
printf ("invert sort data, doulist length is : %d\n",doulist_length(list));
display_list (list);
find_list(list, &data[2], sizeof (int));
destory_list(list);
return 0;
}
三、双向循环链表
3.1 定义数据类型
typedef void * datatype;
typedef struct list_s
{
struct list_s *prev; //指向直接前驱
datatype data; //数据域
struct list_s *next; //指向直接后驱
}list_t;
3.2 生成节点
list_t *create_listloop(void) //新建双向链表
{
list_t *list = NULL;
list = malloc(sizeof(*list));
list->data = NULL;
list->prev = list;
list->next = list;
return list;
}
3.3 插入节点
3.3.1 头/尾插
enum
{
HEADLIST,
TRAILLIST
};
int insert_listloop (list_t *head,const datatype data,int datasize,int mode) //头插、尾插数据
{
list_t *new = NULL;
list_t *q = NULL;
new = malloc( sizeof(*new) );
new->data = malloc(sizeof(datasize));
new->prev = NULL;
new->next = NULL;
memcpy(new->data,data,datasize);
switch(mode) {
case HEADLIST:
new->next=head->next;
new->prev=head;
head->next->prev = new; //必须保证至少有一个数据节点
head->next=new;
break;
case TRAILLIST:
for (q = head; q->next != head; q = q->next);
q->next = new;
new->next = head;
new->prev = q;
break;
default:
free(new->data);
free(new);
return -1;
}
return 0;
}
3.3.2 选择插
int insert_select_listloop (list_t *head, int num, datatype data) //选择插
{
int i;
list_t *q = NULL;
list_t *new = NULL;
if (doulistloop_length (head) < num || num <= 1) {
printf ("insert_select_list num is erorr!\n");
return -1;
}
new = malloc( sizeof(*new) );
new->data = malloc(sizeof (int));
new->prev = NULL;
new->next = NULL;
memcpy(new->data,data,sizeof(int));
for (i = 1, q = head; q->next != head; i++, q = q->next) {
if (i == num) {
new->next = q->next;
new->prev = q;
new->next->prev = new;
q->next = new;
return 0;
}
}
return -1;
}
3.4 打印
int display_listloop (list_t *head) //打印链表
{
list_t *list;
printf ("head : %p <--> ",head);
for(list = head->next; list != head ; list = list->next) {
printf(" %d - %p < -- > ",*((int *)(list->data)), list);
}
printf ("\n");
return 0;
}
3.5 判空
int isempty_listloop (list_t *head) //判空
{
return head->next == head ? 1 : 0;
}
3.6 返回链表长度
int doulistloop_length (list_t *head) //返回链表长度
{
int i;
list_t *q = NULL;
for (i = 0, q = head; q->next != head; q = q->next, i++);
return i;
}
3.7 删除链表某个节点
int delete_listloop(list_t *head, const datatype data, int datasize) //删除链表某个节点
{
list_t *q = NULL;
if(isempty_listloop(head))
return -1;
for(q = head->next; q != head; q = q->next) {
if(!memcmp(q->data,data,datasize)) {
q->prev->next=q->next;
q->next->prev=q->prev;
free (q->data);
return -1;
}
}
return 0;
}
3.8 排序
int func_order(void *s1, void *s2) //作为函数指针,顺序
{
return *((int *)s1) - *((int *)s2);
}
int func_invert(void *s1, void *s2) //作为函数指针,反序
{
return *((int *)s2) - *((int *)s1);
}
int sort_listloop(list_t *head,int (*sort)(void *,void *)) //排序
{
list_t *p;
int i, num, length;
length = doulistloop_length (head);
for(i = 0; i < length - 1; i++) {
num = length - i - 1;
for(p = head->next; num > 0; p = p->next, num--)
{
if(sort(p->data, p->next->data) > 0) {
void *tmp = p->data;
p->data = p->next->data;
p->next->data = tmp;
}
}
}
return 0;
}
3.9 查找某个数据
int find_listloop(list_t *head,const datatype data,int datasize) //查找某个数据
{
list_t *q = NULL;
for(q = head->next; q != head; q = q->next) {
if( !memcmp (q->data,data,datasize) ) {
printf ("find data: %d\n",*((int *)(q->data)));
return 0;
}
}
return -1;
}
3.10 销毁链表
void destory_listloop (list_t *head) //销毁链表
{
list_t *q = NULL;
for(q = head->next->next; q != head; q = q->next) {
free(q->prev->data);
free(q->prev);
}
free(head->data);
free(head);
}
3.11 测试
int main(void)
{
list_t *list = NULL;
int data[10] = {8, 10, 7, 1, 6, 4, 9, 2, 3, 5};
list = create_listloop ();
if (isempty_listloop (list) ) {
printf ("doulist loop is null !\n");
}
insert_listloop (list, &data[0], sizeof (int), TRAILLIST);
insert_listloop (list, &data[1], sizeof (int), TRAILLIST);
insert_listloop (list, &data[2], sizeof (int), TRAILLIST);
insert_listloop (list, &data[3], sizeof (int), TRAILLIST);
printf ("tail insert, doulist loop length is : %d\n",doulistloop_length(list));
display_listloop (list);
insert_listloop (list, &data[4], sizeof (int), HEADLIST);
insert_listloop (list, &data[5], sizeof (int), HEADLIST);
insert_listloop (list, &data[6], sizeof (int), HEADLIST);
insert_listloop (list, &data[7], sizeof (int), HEADLIST);
printf ("head insert, doulist loop length is : %d\n",doulistloop_length(list));
display_listloop (list);
insert_select_listloop (list, 2, &data[8]);
insert_select_listloop (list, 2, &data[9]);
printf ("select insert, doulist loop length is : %d\n",doulistloop_length(list));
display_listloop (list);
delete_listloop(list, &data[1], sizeof (int));
printf ("delete data: 10, doulist loop length is : %d\n",doulistloop_length(list));
display_listloop (list);
sort_listloop (list, func_order);
printf ("order sort data, doulist loop length is : %d\n",doulistloop_length(list));
display_listloop (list);
sort_listloop (list, func_invert);
printf ("invert sort data, doulist loop length is : %d\n",doulistloop_length(list));
display_listloop (list);
find_listloop(list, &data[2], sizeof (int));
destory_listloop(list);
return 0;
}