实现一个双向链表的增删改查

原创 2018年04月15日 12:11:10

        美好的一天从中午起床开始,睡懒觉真的太舒服了,然后我们要上传一份代码,实现双向链表的增删改,首先列出各个函数的功能:

        

void DLinkListInit(DLinkNode** head); 双向链表的初始化
DLinkNode* DLinkListPushBack(DLinkNode* head, DLinkType value); 尾插一个元素
void DLinListPopBack(DLinkNode* head); 尾删一个元素
void DLinkListPushFront(DLinkNode* head, DLinkType value); 头插一个元素
void DLinkListPopFront(DLinkNode* head); 头删一个元素
DLinkNode* DLinkListFind(DLinkNode* head, DLinkType to_find); 根据指定元素值找到并返回节点下标
void DLinkListInsert(DLinkNode* pos, DLinkType value); 往指定位置之前插入一个元素
void DLinkListInsertAfter(DLinkNode* pos, DLinkType value);往指定位置之后插入一个元素

更新:

        更新了双向链表的指定位置删除节点,求链表的长度和是否为空等功能。首先通过列表展示各函数功能

void DLinkListErase(DLinkNode* head,DLinkNode* pos);删除指定位置的节点
void DLinkListRemove(DLinkNode* head,DLinkType value);去除双向链表中第一个值为value的节点
void DLinkListRemoveAll(DLinkNode* head,DLinkType value);去除双向链表中所有值为value的节点
size_t DLinkListSize(DLinkNode* head);求出双向链表的长度
int DLinkListEmpty(DLinkNode* head);判断双向链表是否为空链表,是返回0,否返回1

dlinklist.h

#include<stddef.h>
#include<stdio.h>

typedef char DLinkType;
typedef struct DLinkNode{
	DLinkType data;
	struct DLinkNode* next;
	struct DLinkNode* prev;

}DLinkNode;

void DLinkListInit(DLinkNode** head);

DLinkNode* DLinkListPushBack(DLinkNode* head,DLinkType value);

void DLinkListPushFront(DLinkNode* head,DLinkType value);

void DLinkListPopBack(DLinkNode* head);

void DLinkListPopFront(DLinkNode* head);

DLinkNode* DLinkListFind(DLinkNode* head,DLinkType to_find);

void DLinkListInsert(DLinkNode* head,DLinkNode* pos,DLinkType value);

void DLinkListInsertAfter(DLinkNode* head,DLinkNode* pos,DLinkType value);

更新:

void DLinkListErase(DLinkNode* head,DLinkNode* pos);

void DLinkListRemove(DLinkNode* head,DLinkType value);

void DLinkListRemoveAll(DLinkNode* head,DLinkType value);

size_t DLinkListSize(DLinkNode* head);

int DLinkListEmpty(DLinkNode* head);

dlinklist.c

#include<stdio.h>
#include"dlinklist.h"
#include<stdlib.h>

DLinkNode* CreateDLinkNode(DLinkType value){
	DLinkNode* new_node = (DLinkNode*)malloc(sizeof(DLinkType));
	new_node->data = value;
	new_node->prev = new_node;
	new_node->next = new_node;
	return new_node;
}

void DLinkListInit(DLinkNode** head){
	if(head == NULL){
		return;//feifashuru
	}
	*head == CreateDLinkNode(0);
}

void DestoryNode(DLinkNode* to_delete){
	free(to_delete);
}

DLinkNode* DLinkListPushBack(DLinkNode* head,DLinkType value){
	if(head == NULL){
		return NULL;
	}
	DLinkNode* tail = head->prev;
	DLinkNode* new_node = CreateDLinkNode(value);
	head->prev = new_node;
	new_node->next = head;
	tail->next = new_node;
	new_node->prev = tail;
	return head;
}



void DLinkListPushFront(DLinkNode* head,DLinkType value){
	if(head == NULL){
		return;
	}
	DLinkNode* new_node = CreateDLinkNode(value);
	DLinkNode* cur = head->next;
	cur->prev = new_node;
	new_node->next = cur;
	head->next = new_node;
	new_node->prev = head;
	return;
}

void DLinkListPopBack(DLinkNode* head){
	if(head == NULL){
		return;
	}
	if(head->next == head && head->prev == head){
		return;
	}
	DLinkNode* to_delete = head->prev;
	DLinkNode* pre = to_delete->prev;
	pre->next = head;
	head->prev = pre;
	DestoryNode(to_delete);
	return;
}

void DLinkListPopFront(DLinkNode* head){
	if(head == NULL){
		return;
	}
	if(head->next == head && head->prev == head){
		return;
	}
	DLinkNode* to_delete = head->next;
	DLinkNode* to_delete_next = to_delete->next;
	head->next = to_delete_next;
	to_delete_next->prev = head;
	DestoryNode(to_delete);
	return;
}

DLinkNode* DLinkListFind(DLinkNode* head,DLinkType to_find){
	 if(head == NULL){
		 return NULL;
	 }
	 DLinkNode* cur = head->next;
	 while(cur != head){
		if(cur->data == to_find){
			break;
		}
		cur = cur->next;
	 }
	 if(cur == head){
		 return NULL;
	 }
	 return cur;
}

void DLinkListInsert(DLinkNode* head,DLinkNode* pos,DLinkType value){//pos之前插入
	if(head == NULL || pos == NULL){
		return;
	}
	DLinkNode* new_node = CreateDLinkNode(value);
	DLinkNode* pre = pos->prev;
	new_node->prev = pre;
	pre->next = new_node;

	new_node->next = pos;
	pos->prev = new_node;
	return;
}

void DLinkListInsertAfter(DLinkNode* head,DLinkNode* pos,DLinkType value){
	if(head == NULL || pos == NULL){
		return;
	}
	DLinkNode* cur = pos->next;
	DLinkNode* new_node = CreateDLinkNode(value);
	new_node->next = cur;
	new_node->prev = pos;
	pos->next = new_node;
	cur->prev = new_node;
	return;
}

更新:

void DLinkListErase(DLinkNode* head,DLinkNode* pos){
	if(head == NULL){
		return;
	}
	DLinkNode* cur = pos->next;
	DLinkNode* pre = pos->prev;
	pre->next = cur;
	cur->prev = pre;
	DestoryNode(pos);
	return;
}

void DLinkListRemove(DLinkNode* head,DLinkType value){
	if(head == NULL){
		return;
	}
	DLinkNode* to_remove = DLinkListFind(head,value);
	DLinkNode* to_remove_prev = to_remove->prev;
	DLinkNode* to_remove_next = to_remove->next;
	to_remove_prev->next = to_remove_next;
	to_remove_next->prev = to_remove_prev;
	DestoryNode(to_remove);
	return;
}

void DLinkListRemoveAll(DLinkNode* head,DLinkType value){
	if(head == NULL)	{
		return;
	}
	DLinkNode* to_remove = head->next;
	while(to_remove != head){
		if(to_remove->data == value){
			DLinkListRemove(head,value);
		}
		to_remove = to_remove->next;
	}
	return;	
}

size_t DLinkListSize(DLinkNode* head){
	if(head == NULL){
		return;
	}
	DLinkNode* start = head->next;
	size_t len = 1;
	while(start != head){
		start = start->next;
		++len;
	}
	return len;
}

int DLinkListEmpty(DLinkNode* head){
	if(head == NULL){
		return;
	}
	if(head->next == head && head->prev){
		return 0;
	}
	return 1;
} 



///////////////////////////////////
//测试函数
///////////////////////////////////
#if 1
#include<stdio.h>
#define TEST_HEADER printf("\n=========%s=========\n",__FUNCTION__);
void DLinkListPrintChar(DLinkNode* head,const char* msg){
	printf("[%s]\n",msg);
	DLinkNode* cur = head->next;
	for(;cur != head;cur = cur->next){
		printf("[%c]%p",cur->data,cur);
	}
	for(;cur = head->prev;cur != head){
		printf("[]%c]%p",cur->data,cur);
	}
	printf("\n");
}

测试函数更新:

void TestEmpty(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	DLinkListPushBack(head,'a');
	int ret = DLinkListEmpty(head);
	printf("有内容,excepted 1,actual %d\n",ret);
	DLinkListPopBack(head);
	ret = DLinkListEmpty(head);
	printf("无内容,excepted 0 ,actual %d\n",ret);
}

void TestSize(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	DLinkListPushBack(head,'a');
	DLinkListPushBack(head,'b');
	DLinkListPushBack(head,'c');
	int len = DLinkListSize(head);
	printf("链表的长度为%d\n",len);
	DLinkListPrintChar(head,"输出链表的长度");
}


void TestRemoveAll(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	DLinkListPushBack(head,'a');
	DLinkListPushBack(head,'b');
	DLinkListPushBack(head,'c');
	DLinkListPushBack(head,'b');
	DLinkListRemoveAll(head,'b');
	DLinkListPrintChar(head,"删除此链表中所有的b");
}


void TestRemove(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	DLinkListPushBack(head,'a');
	DLinkListPushBack(head,'b');
	DLinkListPushBack(head,'c');
	DLinkListPushBack(head,'b');
	DLinkListRemove(head,'b');
	DLinkListPrintChar(head,"删除链表中第一个b");
}

void TestErase(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	DLinkListPushBack(head,'a');
	DLinkListPushBack(head,'b');
	DLinkListPushBack(head,'c');
	pos = DLinkListFind(head,'b');
	DLinkListErase(head,pos);
	DLinkListPrintChar(head,"删除pos位置的元素");
}


void TestInsertAfter(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	DLinkListPushBack(head,'a');
	DLinkListPushBack(head,'b');
	DLinkListPushBack(head,'c');
	DLinkNode* pos = DLinkListFind(head,'b');
	DLinkListInsertAfter(head,pos,'y');
	DLinkListPrintChar(head,"在 b 之后插入一个 y");//预期结果:a b y c
}

void TestInsert(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	DLinkListPushBack(head,'a');
	DLinkListPushBack(head,'b');
	DLinkListPushBack(head,'c');
	DLinkNode* pos = DLinkListFind(head,'b');
	DLinkListInsert(head,pos,'x');
	DLinkListPrintChar(head,"在 b 之前插入一个 x");//预期结果:a x b c
}

void TestFind(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	DLinkListPushBack(head,'a');
	DLinkListPushBack(head,'b');
	DLinkListPushBack(head,'c');
	DLinkListFind(head,'c');
	DLinkListPrintChar(head,"查询元素 c");}
void TestPopFront(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	DLinkListPushBack(head,'a');
	DLinkListPushBack(head,'b');
	DLinkListPushBack(head,'c');
	DLinkListPopFront(head);
	DLinkListPrintChar(head,"头删一个元素");
}

void TestPopBack(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	DLinkListPushBack(head,'a');
	DLinkListPushBack(head,'b');
	DLinkListPopBack(head);
	DLinkListPrintChar(head,"尾删一个元素");
}

void TestInit(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	printf("head excepted not NULL,actual %p\n",head);
	printf("data excepted 0,actual %d\n",head->data);
}

void TestPushBack(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	DLinkListPushBack(head,'a');
	DLinkListPushBack(head,'b');
	DLinkListPushBack(head,'c');
	DLinkListPushBack(head,'d');
	DLinkListPrintChar(head,"尾插四个元素");
}


void TestPushFront(){
	TEST_HEADER;
	DLinkNode* head;
	DLinkListInit(&head);
	DLinkListPushFront(head,'a');
	DLinkListPrintChar(head,"头插一个元素");
}

int main(){
	TestInit();
	TestPushBack();
	TestPushFront();
	TestPopBack();
	TestPopFront();
	TestFind();
	TestInsert();
	TestInsertAfter();
	TestErase();
	TestRemove();
	TestRemoveAll();
	TestSize();
	TestEmpty();
	return 0;
}

#endif
        以上就是实现一个双向链表增删改查功能的函数代码,如果你喜欢请为我点个赞,如果代码中有错误或你有更好的想法,请留言,谢谢观看。

应聘者轻专业 招聘者重经验

招聘会上新发现:应聘者轻专业 招聘者重经验  昨天,在国展中心的招聘会上,记者发现,今年应聘人员中,跨专业应聘者比以往有所增加。  北京一家文化传播公司的负责人告诉记者,今年在他们公司应聘的人员中,有...
  • stanely
  • stanely
  • 2001-06-04 16:34:00
  • 590

双向链表的增删改查

// // Created by yex on 2016/12/13. // #ifndef DOUBLELINK_DOUBLELINK_H #define DOUBLELINK_DOUBLELIN...
  • szqsdq
  • szqsdq
  • 2016-12-13 11:40:39
  • 876

PHP实现双向链表

由于需要对一组数据多次进行移动操作,所以写个双向链表。但对php实在不熟悉,虽然测试各个方法没啥问题,就是不知道php语言深层的这些指针和unset有什么注意的地方,贴出来让大家教育吧。效率没测试.....
  • lifushan123
  • lifushan123
  • 2015-05-01 00:31:03
  • 429

双向链表的增删改查操作

阿涛,你要认真对待每一件事,你要潇洒,你要做自己! 前面复习了单向链表和循环链表的操作,写得比较乱,现在写个比较规整的双向链表的的各项操作。 先上个截图: 双向链表的定义和好处我就不说了,说...
  • hadahuluwa
  • hadahuluwa
  • 2012-03-27 18:31:01
  • 3586

java链表之--java双向链表的增删改查

单向链表只能从一个方向遍历链表,即只能查找结点的下一个结点(后继结点),而不能查找结点的上一个结点(前驱结点)。鉴于上述问题,引入了双向链表。由于双向循环链表包含双向链表的所有功能操作。因此,我们只讲...
  • basycia
  • basycia
  • 2016-07-06 15:27:06
  • 440

C语言实现双向链表,增删改查,排序

#include #include typedef struct Node* NodePtr; typedef struct Node { int data; NodePtr prev; N...
  • linxin6560
  • linxin6560
  • 2017-08-01 14:52:14
  • 209

java链表结构(单向、双向的增删改查)

链表介绍 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。 链表与数组的区别 链表和...
  • pengkv
  • pengkv
  • 2015-05-08 10:51:46
  • 1770

PHP实现双向链表并排序 -- 会员排名演示

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。...
  • wuxing26jiayou
  • wuxing26jiayou
  • 2016-07-07 18:15:22
  • 1078

c++实现双向有序链表的,增,删,查,合并

#include using namespace std; struct DouLinkList{     DouLinkList* pre;     int data;     D...
  • qq_16773675
  • qq_16773675
  • 2017-06-02 07:57:52
  • 276

一个指针实现双向链表

用一个指针实现双向链表这个东西除了在面试中能够用到,其他地方哪里会用到,这个我也不知道。希望知道的人能够在评论中说下。 下面直接给出代码 typedef struct _Q1LinkNod...
  • qqMCY
  • qqMCY
  • 2017-03-27 10:18:19
  • 563
收藏助手
不良信息举报
您举报文章:实现一个双向链表的增删改查
举报原因:
原因补充:

(最多只允许输入30个字)