-
带头双向循环链表:
结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势.
-
具体接口实现如下:
-
<List.h>
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <assert.h>
typedef int LTDataType;
typedef struct ListNode
{
LTDataType _data;
struct ListNode* _next;
struct ListNode* _prev;
}ListNode;
typedef struct List
{
ListNode* _head;
}List;
void ListInit(List* plist);
void ListDestroy(List* plist);
void ListPushBack(List* plist, LTDataType x);
void ListPopBack(List* plist);
void ListPushFront(List* plist, LTDataType x);
void ListPopFront(List* plist);
ListNode* ListFind(List* plist, LTDataType x);
//在pos之前进行插入
void ListInsert(ListNode* pos, LTDataType x);
//删除pos位置的节点
void ListErase(ListNode* pos);
void ListPrint(List* plist);
-
<List.c>
#include "List.h"
ListNode* BuyListNode(LTDataType x)
{
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
assert(node);
node->_data = x;
node->_next = NULL;
node->_prev = NULL;
return node;
}
void ListInit(List* plist)
{
assert(plist);
plist->_head = BuyListNode(0);
plist->_head->_next = plist->_head;
plist->_head->_prev = plist->_head;
}
void ListDestroy(List* plist)
{
assert(plist);
ListNode* cur = plist->_head->_next;
while (cur != plist->_head)
{
ListNode* next = cur->_next;
free(cur);
cur = next;
}
free(plist->_head);
plist->_head = NULL;
}
void ListPushBack(List* plist, LTDataType x)
{
assert(plist);
ListNode* head = plist->_head;
ListNode* tail = head->_prev;
ListNode* newnode = BuyListNode(x);
tail->_next =newnode;
newnode->_prev = tail;
newnode->_next = head;
head->_prev = newnode;
}
void ListPopBack(List* plist)
{
assert(plist);
ListNode* head = plist->_head;
ListNode* tail = head->_prev;
ListNode* prev = tail->_prev;
prev->_next = head;
head->_prev = prev;
free(tail);
}
void ListPushFront(List* plist, LTDataType x)//头插时,在head的后面插入
{
assert(plist);
ListNode* head = plist->_head;
ListNode* next = head->_next;
ListNode* newnode = BuyListNode(x);
head->_next = newnode;
newnode->_prev = head;
newnode->_next = next;
next->_prev = newnode;
}
void ListPopFront(List* plist)
{
assert(plist);
ListNode* head = plist->_head;
ListNode* next = head->_next;
ListNode* nextnext = next->_next;
if (head == next)
return;
head->_next = nextnext;
nextnext->_prev = head;
free(next);
next = NULL;
}
ListNode* ListFind(List* plist, LTDataType x)
{
assert(plist);
ListNode* cur = plist->_head->_next;
while (cur != plist->_head)
{
if (cur->_data == x)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
void ListInsert(ListNode* pos, LTDataType x)//在pos之前进行插入
{
assert(pos);
ListNode* prev = pos->_prev;
ListNode* newnode = BuyListNode(x);
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = pos;
pos->_prev = newnode;
}
void ListErase(ListNode* pos)//删除pos位置的节点
{
assert(pos);
ListNode* prev = pos->_prev;
ListNode* next = pos->_next;
prev->_next = next;
next->_prev = prev;
free(pos);
pos = NULL;
}
void ListPrint(List* plist)
{
assert(plist);
ListNode* cur = plist->_head->_next;
while (cur != plist->_head)
{
printf("%d->", cur->_data);
cur = cur->_next;
}
printf("<=>\n");
}
-
<test.c>
#include "List.h"
ListTest()
{
List lt;
ListInit(<);
ListPushBack(<,1);
ListPushBack(<,2);
ListPushBack(<,3);
ListPushBack(<,4);
ListPushBack(<,5);
ListPopBack(<);
ListPushFront(<, 0);
ListPopFront(<);
ListNode* pos = ListFind(<, 2);
ListInsert(pos, 5);
ListErase(pos);
ListPrint(<);
}
int main()
{
ListTest();
system("pause");
return 0;
}
-
顺序表和链表的区别和联系
顺序表:一白遮白丑
白:空间连续、支持随机访问
丑: 1. 中间或前面部分的插入删除时间复杂度O(N)
2.增容的代价比较大。
链表:一胖毁所有
黑: 以节点为单位存储,不支持随机访问
所有: 1.任意位置插入删除时间复杂度为0(1)
2.没有增容问题,插入一个开辟一个空间。