1,双向链表的构成
双向链表一般是由一个头节点和若干个普通结点组成的,而头节点的结构如下
struct List
{
int size;//用来对链表中的结点计数
struct Node* firstNode;//指向第一个结点
struct Node* lastNode;//指向最后一个结点
};
一般结点结构如下
struct Node
{
int data;//储存数据
struct Node* right;//指向上一个结点
struct Node* left;//指向下一个结点
};
2,双向链表的创建
创建双向链表,首先就是要创建头节点
struct List* createList()
{
struct List* list = (struct List*)malloc(sizeof(List));//使用malloc函数动态分配空间
list->firstNode = list->lastNode = NULL;
return list;
}
3,插入结点
一般来说,双链表中,插入结点的方法有三种,分别为头插法,尾插法和指定位置插入法
1,头插法
头插法,顾名思义,就是在链表的开头插入一个新的结点,代码如下
struct Node* createNode(int data)
{
struct Node* newNode = (struct Node*)malloc(sizeof(Node));//使用malloc函数动态分配空间
newNode->data = data;//储存数据
newNode->right = newNode->left = NULL;
return newNode;
}
void insertNodeByHead(struct List* list, int data)
{
struct Node* newNode = createNode(data);
if (list->firstNode == NULL)//如果链表为空,直接将新的结点变成第一个结点和最后一个结点
{
list->firstNode = newNode;
list->lastNode = newNode;
}
else
{
list->firstNode->left = newNode;
newNode->right = list->firstNode;
list->firstNode = newNode;
}
list->size++;//链表中结点数目加一
}
2,尾插法
尾插法,和头插法原理一样,只不过是从最后一个结点插入,这里就不多说,代码如下
struct Node* createNode(int data)
{
struct Node* newNode = (struct Node*)malloc(sizeof(Node));//使用malloc函数动态分配空间
newNode->data = data;//储存数据
newNode->right = newNode->left = NULL;
return newNode;
}
void insertNodeByTail(struct List* list, int data)
{
struct Node* newNode = createNode(data);
if (list->firstNode == NULL)
{
list->firstNode = newNode;
list->lastNode = newNode;
}
else
{
list->lastNode->right = newNode;
newNode->left = list->lastNode;
list->lastNode = newNode;
}
list->size++;
}
3,指定位置插入
接下来就是指定位置插入法了,指定位置插入法是三种插入方法中最难,但也是用处最广泛的方法,它的原理是从第一个结点开始向后寻找,当找到指定的结点是,将新的结点插到它的前面,代码如下
struct List* createList()
{
struct List* list = (struct List*)malloc(sizeof(List));//使用malloc函数动态分配空间
list->firstNode = list->lastNode = NULL;
return list;
}
void insertNodeByAppoin(struct List* list, int posdata, int data)
{
if (list->firstNode == NULL)
{
printf("链表为空\n");
}
else if (list->firstNode->data == posdata)
{
insertNodeByHead(list, data);
}
else
{
struct Node* posNode = list->firstNode->right;
struct Node* posNodeFront = list->firstNode;
while (posNode->data != posdata && posNode != NULL)//当没有找到合适的结点,就向后循环
{
posNodeFront = posNode;
posNode = posNode->right;
}
if (posNode == NULL)
{
printf("无法找到\n");
}
else
{
struct Node* newNode = createNode(data);
newNode->left = posNodeFront;
newNode->right = posNode;
posNode->left = newNode;
posNodeFront->right = newNode;
list->size++;
}
}
}
3,结点的删除
结点的删除和插入很相似,但删除一般只有指定位置删除法,代码如下
void deleteNodeByAppoin(struct List* list, int posdata)
{
struct Node* posNode = list->firstNode;
struct Node* posNodeFront = NULL;
while (posNode->data != posdata)//找到指定位置
{
posNodeFront = posNode;
posNode = posNode->right;
}
posNodeFront->right = posNode->right;
free(posNode);//删除结点
}
4,链表的打印
链表的打印没什么多说的,代码如下
void printList(struct List* list)
{
struct Node* pMove = list->firstNode;
while (pMove)
{
printf("%d", pMove->data);//打印该节点的数据
pMove = pMove->right;//指向下一个结点
}
}