双向循环链表与单向list相比较,虽然它的管理方式看起来比单向list复杂,多了一个前驱指针,但是它的实现就简单多了,因为它能轻松的找到当前节点的前驱节点进行操作。
1.DCList.h
链表增删改查等操作的实现;
#ifndef __DCLIST_H__
#define __DCLIST_H__
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#include<stdio.h>
#include<windows.h>
#pragma warning(disable:4996)
#define ElemTepe int
typedef struct DCListNode //链表节点
{
ElemTepe data;
struct DCListNode* next; //后继节点
struct DCListNode* pre; //前驱节点
}DCListNode;
typedef struct DCList //头节点 方便对节点的管理
{
DCListNode* first;
DCListNode* last;
size_t size;
}DCList;
DCListNode* _BuyDCLNode(ElemTepe x) { //申请一个链表节点
DCListNode* s = (DCListNode*)malloc(sizeof(DCListNode));
assert(s != NULL);
s->next = s->pre = NULL;
s->data = x;
return s;
}
void DCSListInit(DCList* plist); //初始化
void DCListShow(DCList* plist); //自己添加了一个显示功能,方便查看
void DCListPushBack(DCList* plist, ElemTepe x); //尾部插入
void DCListPushFront(DCList * plist, ElemTepe x);//头部插入
void DCListPopBack(DCList * plist); //尾部删除
void DCListPopFront(DCList* plist); //头部删除
void DCListClear(DCList* plist); //清空
void DCListDestroy(DCList* plist); //摧毁
void DCListReverse(DCList* plist); //翻转
void DCListDeleteByVal(DCList* plist, ElemTepe x); //按元素删除
DCListNode* DCListFind(DCList* plist, ElemTepe x); //按元素查找
void DCListInsertByVal(DCList* plist, ElemTepe x); //按元素插入
void DCListReverse(DCList* plist) {
assert(plist);
DCListNode* p = plist->first->next;
DCListNode* q ;
if (plist->size <= 1) {
return;
}
//将第一个节点与后面的节点断开
q = p->next;
p->next = plist->first;
plist->first->pre = p;
plist->last = p;
while (q != plist->first) {//逐个去除后面的节点进行push_front
p = q;
q = q->next;
p->next = plist->first->next;
plist->first->next = p;
p->pre = plist->first;
p->next->pre = p;
}
}
void DCListPopBack(DCList* plist) {
assert(plist);
if (plist->first == plist->last) {
printf("数据为空无法删除!\n");
}
DCListNode* p = plist->last;
plist->last = p->pre;
p->pre->next = p->next;
p->next->pre = p->pre;
free(p);
plist->size--;
}
void DCListPopFront(DCList* plist)
{
assert(plist);
if (plist->first == plist->last) {
printf("数据为空无法删除!\n");
}
DCListNode* p = plist->first->next;
plist->first->next = p->next;
p->next->pre = plist->first;
if (p == plist->last) {//只有一个节点
plist->last = plist->first;
}
free(p);
plist->size--;
}
void DCListClear(DCList* plist) {
assert(plist);
DCListNode* p = plist->first->next;
DCListNode* pre;
while (p == plist->first) {
pre = p;
p = p->next;
free(pre);
}
plist->last = plist->first;
plist->first->pre = plist->first->next = plist->first;
plist->size = 0;
}
void DCListDestroy(DCList* plist) {
DCListClear(plist);
free(plist->first);
}
void DCSListInit(DCList* plist) {
assert(plist);
DCListNode* p = _BuyDCLNode(0);
plist->first = plist->last = p;
plist->first->next = plist->first->pre = p;
plist->size = 0;
}
void DCListShow(DCList* plist) {
DCListNode* p = plist->first->next;
while (p != plist->first) {
printf("%d->", p->data);
p = p->next;
}
printf("over \n");
}
void DCListPushBack(DCList* plist, ElemTepe x) {
assert(plist);
DCListNode* s = _BuyDCLNode(x);
DCListNode* p = plist->last;
s->pre = p;
p->next = s;
plist->last = s;
s->next = plist->first;
plist->first->pre = plist->last;
plist->size++;
}
void DCListPushFront(DCList* plist, ElemTepe x) {
assert(plist);
DCListNode* s = _BuyDCLNode(x);
DCListNode* p = plist->first;
s->next = p->next;
s->pre = p;
s->pre->next = s;
s->next->pre = s;
plist->size++;
if (plist->first == plist->last) {
plist->last = s;
}
}
DCListNode* DCListFind(DCList* plist, ElemTepe key) {
assert(plist);
DCListNode* p = plist->first->next;
while ((plist->first != p) && p->data != key) {
p = p->next;
}
if (p == plist->first) {
return NULL;
}
return p;
}
void DCListDeleteByVal(DCList* plist, ElemTepe key)
{
assert(plist);
DCListNode* s = DCListFind(plist, key);
if (s == NULL) {
printf("要删的值不存在");
return;
}
if (s == plist->last) {
plist->last = s->pre;
}
s->pre->next = s->next;
s->next->pre = s->pre;
free(s);
plist->size--;
}
void DCListInsertByVal(DCList* plist, ElemTepe key) {
assert(plist);
DCListNode* s = _BuyDCLNode(key);
DCListNode* p = plist->first->next;
while ((plist->first != p) && p->data < key) {
p = p->next;
}
p->pre->next = s;
s->pre = p->pre;
s->next = p;
p->pre = s;
if (p == plist->first) { //尾插
plist->last = plist->first->pre;
}
plist->size++;
}
2.main.c
测试各个函数功能
#include"DCList.h"
int main()
{
DCList mylist;
DCSListInit(&mylist);
ElemTepe item, key;
int pos;
DCListNode* p;
int select = 1;
while (select)
{
printf("********************************************\n");
printf("* [0] quit_system [1] push_back *\n");
printf("* [2] push_front [3] show_list *\n");
printf("* [4] pop_back [5] pop_front *\n");
printf("* [6] length [7] insert_val *\n");
printf("* [8] delete_val [9] find *\n");
printf("* [10] sort [11] reverse *\n");
printf("* [12] remove_all [13] clear *\n");
printf("********************************************\n");
printf("请选择:>");
scanf("%d", &select);
switch (select)
{
case 1:
printf("请输入要插入的数据(以-1结束):>");
while (scanf("%d", &item), item != -1) //逗号表达式
DCListPushBack(&mylist, item);
break;
case 2:
printf("请输入要插入的数据(以-1结束):>");
while (scanf("%d", &item), item != -1) //逗号表达式
DCListPushFront(&mylist, item);
break;
case 3:
DCListShow(&mylist);
break;
case 4:
DCListPopBack(&mylist);
break;
case 5:
DCListPopFront(&mylist);
break;
case 6:
printf("表长为:>%d\n", mylist.size);
break;
case 7:
printf("请输入要插入的值:>");
scanf("%d", &item);
DCListInsertByVal(&mylist, item);
break;
case 8:
printf("请输入要删除的值:>");
scanf("%d", &key);
DCListDeleteByVal(&mylist, key);
break;
case 9:
printf("请输入要查找的值:>");
scanf("%d", &key);
p = DCListFind(&mylist, key);
if (p == NULL)
printf("要查找的值%d不存在.\n", key);
else
printf("要查找的值%d存在.\n", key);
break;
case 10:
DCListSort(&mylist);
break;
case 11:
DCListReverse(&mylist);
break;
//case 12:
// printf("请输入要删除的值:>");
// scanf("%d", &key);
// DCSListRemoveAll(&mylist, key);
// break;
case 13:
DCListClear(&mylist);
break;
default:
break;
}
system("pause");
DCListShow(&mylist);
/*system("cls");*/
}
DCListDestroy(&mylist);
return 0;
}