双向链表
双向链表顾名思义,各个节点前后都相连。就像下图表示的那样。
尾插法
既然是链表,那么就存在两种元素的插入方式。一为头插法,二为尾插法。我们现在介绍一下尾插法如何实现。
- 假设当前链表中有一个元素。
- 然后在元素1的后面插入新的节点。
- 插入完毕
头插法
双向链表的头插法与单链表的头插法是相似的。只不过增加了向前的指针罢了。
- 假设链表中已有一个元素
- 生成新节点,并在head后方插入新节点
- 插入完成.
C语言代码
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct node
{
int data;
struct node* next;
struct node* pre;
}List;
void _list_init(List* head)
{
if (head == NULL)
{
printf("head node is NULL\n");
assert(0);
}
else
{
List* temp = head;
temp->next = NULL;
temp->pre = NULL;
temp->data = -1;
}
}
void _insert_element_one_by_one(List* head, int num)//头插法
{
if (head == NULL)
{
printf("head node is NULL\n");
assert(0);
}
else
{
List* temp = head;
List* new_node = (List*)malloc(sizeof(List));
new_node->data = num;
new_node->next = temp->next;
new_node->pre = temp;
temp->next = new_node;
if (new_node->next != NULL)
{
new_node->next->pre = new_node;
}
}
}
void _INSERT_ELEMENT_ONE_BY_ONE(List* head, int num)//尾插法
{
if (head == NULL)
{
printf("head node is NULL\n");
assert(0);
}
else
{
List* temp = head;//生成临时头节点
while (temp->next != NULL)
{
temp = temp->next;
}
List* new_node = (List*)malloc(sizeof(List));
new_node->data = num;
new_node->next = NULL;
new_node->pre = temp;
temp->next = new_node;
}
}
void print_list_R_order(List* head)//逆序
{
if (head == NULL)
{
printf("head node is NULL\n");
assert(0);
}
else
{
List* temp = head->next;
while (temp->next!= NULL)
{
temp = temp->next;//找到最后一个节点
}
while (temp != head)
{
printf("%d ", temp->data);
temp = temp->pre;
}
printf("\n");
}
}
void print_list_order(List* head)//从左到右
{
if (head == NULL)
{
printf("head node is NULL\n");
assert(0);
}
else
{
List* temp = head->next;
while (temp != NULL)
{
printf("%d ", temp->data);
temp = temp->next;//找到最后一个节点
}
printf("\n");
}
}
int delete_element(List* head, int num)
{
if (head == NULL)
{
printf("List is NULL\n");
assert(0);
}
else {
List* slow = head;
List* finder = head->next;//快指针
while (finder != NULL)
{
if (finder->data == num)
{
slow->next = finder->next;
finder->next = slow;
free(finder);
break;
}
slow = slow->next;
finder = finder->next;
}
}
return 0;//没找到指定元素
}
int insert_element_behind_some_element(List* head,int num,int ele)
{
if (head == NULL)
{
printf("List is NULL\n");
assert(0);
}
else {
List* finder = head->next;//快指针
while (finder != NULL)
{
if (finder->data == num)
{
List* new_node = (List*)malloc(sizeof(List));
new_node->data = ele;
new_node->next = finder->next;
finder->next = new_node;
new_node->pre = finder;
new_node->next->pre = new_node;
break;
}
finder = finder->next;
}
}
return 0;//没找到指定元素
}
int get_list_length(List* head)
{
List* temp = head->next;
int count = 0;
while (temp != NULL)
{
count++;
temp = temp->next;
}
return count;
}
int main()
{
List* l = (List*)malloc(sizeof(List));
List* L = (List*)malloc(sizeof(List));
_list_init(l);
_list_init(L);
for (int i = 0; i < 10; i++)
{
printf("%d ", i);
_insert_element_one_by_one(l,i); //头插
_INSERT_ELEMENT_ONE_BY_ONE(L, i);//尾插
}
printf("\n");
printf("print list l :");
print_list_order(l);
printf("print list l Reverse:");
print_list_R_order(l);
printf("print list L :");
print_list_order(L);
printf("print list L Reverse:");
print_list_R_order(L);
printf("delete element 8 at list l\n");
delete_element(l, 8);
printf("print list l :");
print_list_order(l);
printf("delete element 8 at list L\n");
delete_element(L, 8);
printf("print list L :");
print_list_order(L);
printf("insert 3 behind 3 at l\n");
insert_element_behind_some_element(l, 3, 3);
printf("print list l :");
print_list_order(l);
printf("insert 3 behind 3 at L\n");
insert_element_behind_some_element(L, 3, 3);
printf("print list L :");
print_list_order(L);
}
以上代码执行结果
稍后会有循环链表,链表栈,链表队列~