1.双向链表的实现
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
//带头+双向+循环链表增删查改实现
typedef int LTDateType;
typedef struct ListNode
{
LTDateType data;//数据域
struct ListNode* next;//前驱指针
struct ListNode* prev;//后驱指针
}LTNode;
//创建返回链表的头结点.
LTNode* ListInit();
// 双向链表销毁
void ListDestroy(LTNode* phead);
// 双向链表打印
void ListPrint(LTNode* phead);
//申请新节点
LTNode* BuyListNode(LTDateType x);
// 双向链表尾插
void ListPushBack(LTNode* phead, LTDateType x);
// 双向链表尾删
void ListPopBack(LTNode* phead);
// 双向链表头插
void ListPushFront(LTNode* phead, LTDateType x);
// 双向链表头删
void ListPopFront(LTNode* phead);
// 双向链表查找
LTNode* ListFind(LTNode* phead, LTDateType x);
// 双向链表在pos的前面进行插入
void ListInsert(LTNode* pos, LTDateType x);
// 双向链表删除pos位置的节点
void ListErase(LTNode* pos);
1.1 创建返回链表的头结点.
LTNode* ListInit()
{
//哨兵位头结点
LTNode* phead = (LTNode*)malloc(sizeof(LTNode));
phead->next = phead;
phead->prev = phead;
return phead;
}
1.2 双向链表销毁
void ListDestroy(LTNode* phead)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
LTNode* next = cur->next;
free(cur);
cur = next;
}
free(phead);
phead = NULL;//这样写没有什么作用,因为phead是形参,形参改变不会影响实参 //也就是pList不会改变。
//phead已经被释放了,此时pList就是一个野指针。
//我们需要在外面,即test.c文件中把它置空
//ListDestroy(pList);
//pList = NULL;//外面置空
}
1.3双向链表打印
void ListPrint(LTNode* phead)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}
1.4申请新节点
LTNode* BuyListNode(LTDateType x)
{
LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
newnode->data = x;
newnode->next = NULL;
newnode->prev = NULL;
return newnode;
}
1.5双向链表尾插
void ListPushBack(LTNode* phead, LTDateType x)
{
assert(phead);
LTNode* tail = phead->prev;
LTNode* newnode = BuyListNode(x);
tail->next = newnode;
newnode->prev = tail;
newnode->next = phead;
phead->prev = newnode;
//ListInsert(phead,x);
}
1.6双向链表尾删
//void ListPopBack(LTNode* phead)
//{
// assert(phead);
// assert(phead->next != phead);//防止删了头结点
//
// LTNode* tail = phead->prev;
// LTNode* tailPrev = tail->prev;
// free(tail);
// tailPrev->next = phead;
// phead->prev = tailPrev;
// //ListErase(phead->prev);
//}
void ListPopBack(LTNode* phead)
{
assert(phead);
assert(phead->next != phead);
LTNode* tail = phead->prev;
phead->prev = tail->prev;
tail->prev->next = phead;
free(tail);
//ListErase(phead->prev);
}
1.7双向链表头插
void ListPushFront(LTNode* phead, LTDateType x)
{
assert(phead);
LTNode* newnode = BuyListNode(x);
LTNode* next = phead->next;
phead->next = newnode;
newnode->prev = phead;
newnode->next = next;
next->prev = newnode;
//ListInsert(phead->next,x);
}
1.8 双向链表查找
LTNode* ListFind(LTNode* phead, LTDateType x)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
1.9双向链表在pos的前面进行插入
void ListInsert(LTNode* pos, LTDateType x)
{
assert(pos);
LTNode* posPrev = pos->prev;
LTNode* newnode = BuyListNode(x);
posPrev->next = newnode;
newnode->prev = posPrev;
newnode->next = pos;
pos->prev = newnode;
}
1.10双向链表删除pos位置的节点
void ListErase(LTNode* pos)
{
assert(pos);
LTNode* posPrev = pos->prev;
LTNode* posNext = pos->next;
posPrev->next = posNext;
posNext->prev = posPrev;
free(pos);
pos = NULL;
}
List.h
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
//带头+双向+循环链表增删查改实现
typedef int LTDateType;
typedef struct ListNode
{
LTDateType data;//数据域
struct ListNode* next;//前驱指针
struct ListNode* prev;//后驱指针
}LTNode;
//创建返回链表的头结点.
LTNode* ListInit();
// 双向链表销毁
void ListDestroy(LTNode* phead);
// 双向链表打印
void ListPrint(LTNode* phead);
//申请新节点
LTNode* BuyListNode(LTDateType x);
// 双向链表尾插
void ListPushBack(LTNode* phead, LTDateType x);
// 双向链表尾删
void ListPopBack(LTNode* phead);
// 双向链表头插
void ListPushFront(LTNode* phead, LTDateType x);
// 双向链表头删
void ListPopFront(LTNode* phead);
// 双向链表查找
LTNode* ListFind(LTNode* phead, LTDateType x);
// 双向链表在pos的前面进行插入
void ListInsert(LTNode* pos, LTDateType x);
// 双向链表删除pos位置的节点
void ListErase(LTNode* pos);
List.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
LTNode* ListInit()
{
//哨兵位头结点
LTNode* phead= (LTNode*)malloc(sizeof(LTNode));
phead->next = phead;
phead->prev = phead;
return phead;
}
LTNode* BuyListNode(LTDateType x)
{
LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
newnode->data = x;
newnode->next = NULL;
newnode->prev = NULL;
return newnode;
}
void ListPrint(LTNode* phead)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}
void ListPushBack(LTNode* phead, LTDateType x)
{
assert(phead);
LTNode* tail = phead->prev;
LTNode* newnode = BuyListNode(x);
tail->next = newnode;
newnode->prev = tail;
newnode->next = phead;
phead->prev = newnode;
//ListInsert(phead,x);
}
//void ListPopBack(LTNode* phead)
//{
// assert(phead);
// assert(phead->next != phead);//防止删了头结点
//
// LTNode* tail = phead->prev;
// LTNode* tailPrev = tail->prev;
// free(tail);
// tailPrev->next = phead;
// phead->prev = tailPrev;
// //ListErase(phead->prev);
//}
void ListPopBack(LTNode* phead)
{
assert(phead);
assert(phead->next != phead);
LTNode* tail = phead->prev;
phead->prev = tail->prev;
tail->prev->next = phead;
free(tail);
//ListErase(phead->prev);
}
void ListPushFront(LTNode* phead, LTDateType x)
{
assert(phead);
LTNode* newnode = BuyListNode(x);
LTNode* next = phead->next;
phead->next = newnode;
newnode->prev = phead;
newnode->next = next;
next->prev = newnode;
//ListInsert(phead->next,x);
}
void ListPopFront(LTNode* phead)
{
assert(phead);
assert(phead->next != phead);
LTNode* next = phead->next;
LTNode* nextNext = next->next;
phead->next = nextNext;
nextNext->prev = phead;
free(next);
//ListErase(phead->next);
}
LTNode* ListFind(LTNode* phead, LTDateType x)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
//pos位置之前插入
void ListInsert(LTNode* pos, LTDateType x)
{
assert(pos);
LTNode* posPrev = pos->prev;
LTNode* newnode = BuyListNode(x);
posPrev->next = newnode;
newnode->prev = posPrev;
newnode->next = pos;
pos->prev = newnode;
}
//删除pos位置
void ListErase(LTNode* pos)
{
assert(pos);
LTNode* posPrev = pos->prev;
LTNode* posNext = pos->next;
posPrev->next = posNext;
posNext->prev = posPrev;
free(pos);
pos = NULL;
}
void ListDestroy(LTNode* phead)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
LTNode* next = cur->next;
free(cur);
cur = next;
}
free(phead);
phead = NULL;//这样写没有什么作用,因为phead是形参,形参改变不会影响实参 //也就是pList不会改变。
//phead已经被释放了,此时pList就是一个野指针。
//我们需要在外面,即test.c文件中把它置空
//ListDestroy(pList);
//pList = NULL;//外面置空
}
Test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
void test1()
{
LTNode* plist = ListInit();
ListInit(plist);
ListPushBack(plist, 1);
ListPushBack(plist, 2);
ListPushBack(plist, 3);
ListPushBack(plist, 4);
ListPrint(plist);
ListPopBack(plist);
ListPopBack(plist);
ListPopBack(plist);
ListPopBack(plist);
ListPrint(plist);
}
void test2()
{
LTNode* plist = ListInit();
ListInit(plist);
ListPushFront(plist, 1);
ListPushFront(plist, 2);
ListPushFront(plist, 3);
ListPushFront(plist, 4);
ListPrint(plist);
ListPopFront(plist);
ListPopFront(plist);
ListPopFront(plist);
ListPopFront(plist);
ListPrint(plist);
}
void test3()
{
LTNode* plist = ListInit();
ListInit(plist);
ListPushFront(plist, 1);
ListPushFront(plist, 2);
LTNode* pos = ListFind(plist, 2);
if (pos)
{
ListInsert(pos,20);
}
ListPrint(plist);
pos = ListFind(plist, 2);
if (pos)
{
ListErase(pos);
}
ListPrint(plist);
ListDestroy(plist);
plist = NULL;
}
int main()
{
test1();
test2();
test3();
return 0;
}
顺序表和链表的区别