【数据结构】双链表接口的实现

  • 带头双向循环链表:

结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势.

  • 具体接口实现如下:

  • <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(&lt);

	ListPushBack(&lt,1);
	ListPushBack(&lt,2);
	ListPushBack(&lt,3);
	ListPushBack(&lt,4);
	ListPushBack(&lt,5);
	ListPopBack(&lt);
	ListPushFront(&lt, 0);
	ListPopFront(&lt);
	ListNode* pos = ListFind(&lt, 2);
	ListInsert(pos, 5);
	ListErase(pos);
	ListPrint(&lt);
	



}


int main()
{
	ListTest();
	system("pause");
	return 0;
}

 

  • 顺序表和链表的区别和联系

顺序表:一白遮白丑
白:空间连续、支持随机访问
丑: 1. 中间或前面部分的插入删除时间复杂度O(N)
     2.增容的代价比较大。


链表:一胖毁所有
黑: 以节点为单位存储,不支持随机访问
所有: 1.任意位置插入删除时间复杂度为0(1) 
2.没有增容问题,插入一个开辟一个空间。

猜你喜欢

转载自blog.csdn.net/qq_42270373/article/details/83033757