doubly linked list
The code I got online can be said to be excellent.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <ctype.h>
#define LIST_ELEM_TYPE int /*链表元素数据类型*/
LIST_ELEM_TYPE largest=1 ;
/*链表节点类型*/
typedef struct Node {
LIST_ELEM_TYPE Data;
struct Node * Prior;
struct Node * Next;
} Node;
/*双向循环链表类型*/
typedef struct List {
Node * Head;
int Length;
} List;
/*创建新的链表*/
List * CreateList(void) {
List * list = (List *) calloc(1, sizeof(List));
list->Head = NULL;
list->Length = 0;
return (list);
}
/*创建值为value的新节点*/
Node * CreateNode(LIST_ELEM_TYPE value) {
Node * node = (Node *) calloc(1, sizeof(Node));
node->Data = value;
node->Prior = NULL;
node->Next = NULL;
return (node);
}
/*在链表结尾附加节点*/
int AppendElement(List * list, LIST_ELEM_TYPE value) {
if (0 == list->Length) { /*若链表为空,则新节点成为第一个节点*/
list->Head = CreateNode(value);
list->Head->Next = list->Head;
list->Head->Prior = list->Head;
list->Length = 1;
}
else {
Node * node = CreateNode(value);
node->Next = list->Head;
node->Prior = list->Head->Prior;
list->Head->Prior->Next = node;
list->Head->Prior = node;
++(list->Length);
}
return (0);
}
/*在链表中pos位置处插入元素value*/
int InsertElement(List * list, int pos, LIST_ELEM_TYPE value) {
if (((1 <= pos) && (pos <= (list->Length + 1))) ==0) {
return (2);
}
else if (0 == list->Length) {
list->Head = CreateNode(value);
list->Head->Next = list->Head;
list->Head->Prior = list->Head;
list->Length = 1;
}
else {
Node * newNode = CreateNode(value);
Node * node = list->Head;
int cnt;
for (cnt = 1; cnt < pos; cnt++) {
node = node->Next;
}
newNode->Next = node;
newNode->Prior = node->Prior;
node->Prior->Next = newNode;
node->Prior = newNode; /*插入新节点*/
if (1 == pos) {
list->Head = newNode;
} /*若新节点为一号节点,则更新链表头指针*/
++(list->Length);
}
return (0);
}
/*删除链表并对占用的存储空间进行回收*/
int DisposeList(List * list) {
if (NULL == list) {
return (0); /*若链表不存在,则直接返回*/
}
if (0 == list->Length) {
free(list);
}
else {
Node * head = list->Head;
Node * node = head;
Node * todo;
do {
todo = node->Next;
free(node);
node = todo;
} while (head != node); /*遍历链表,并回收各元素的存储空间*/
free(list);
}
return (0);
}
/*将链表重置为空表*/
int ClearList(List * list) {
if (0 == list->Length) {
list->Head = NULL;
}
else {
Node * head = list->Head;
Node * node = head;
Node * todo;
do {
todo = node->Next;
free(node);
node = todo;
} while (head != node);
list->Head = NULL;
list->Length = 0;
}
return (0);
}
/*判断链表是否为空*/
int IsListEmpty(List * list) {
if (NULL == list) {
return (1);
}
else if (0 == list->Length) {
return (1);
}
else {
return (0);
}
}
/*返回链表元素个数*/
int ListLength(List * list) {
if (NULL == list) {
return (3);
}
else {
return (list->Length);
}
}
/*链表中pos位置删除元素,并将数据存于value中*/
int DeleteElement(List * list, int pos, LIST_ELEM_TYPE * value) {
if (NULL == list) {
return (3); /*判断链表是否存在*/
}
else if (((1 <= pos) && (pos <= (list->Length))) ==0) {
return (2); /*判断pos位置是否存在*/
}
else {
Node * node = list->Head;
int cnt;
for (cnt = 1; cnt < pos; cnt++) {
node = node->Next;
} /*遍历链表,查找第pos个元素*/
*value = node->Data;
node->Next->Prior = node->Prior;
node->Prior->Next = node->Next;
if (1 == pos) {
list->Head = node->Next;
} /*若是第一个元素,则更新链表头指针*/
free(node);
if (0 == (--(list->Length))) {
list->Head = NULL;
}
return (0);
}
}
/*链表中删除第一个值为value的元素*/
int DeleteData(List * list, LIST_ELEM_TYPE value) {
if (NULL == list) {
return (3); /*判断链表是否存在*/
}
else if (0 == list->Length) {
return (2);
}
else {
Node * head = list->Head;
Node * node = head;
do {
if (value == node->Data) {
break;
}
node = node->Next;
} while (node != head); /*遍历链表,查找值为value的元素*/
if (value != node->Data) {
return (4);
}
node->Next->Prior = node->Prior;
node->Prior->Next = node->Next;
if (list->Head == node) {
list->Head = node->Next;
}
free(node);
if (0 == (--(list->Length))) {
list->Head = NULL;
}
return (0);
}
}
/*比较数字a和b的是否相等*/
int NumberCompare(LIST_ELEM_TYPE * a, LIST_ELEM_TYPE * b) {
if ((*a) == (*b)) {
return (1);
}
else {
return (0);
}
}
/*查询链表中第一处与value满足compare()关系的元素位置,结果存放在pos中*/
int LocateElement(List * list, int * pos, LIST_ELEM_TYPE value, int (*compare)(void *, void *)) {
if (NULL == list) {
return (3);
}
else {
int cnt = 1;
int len = list->Length;
Node * head = list->Head;
Node * node = head;
do {
if ( compare(&value, &(node->Data))==1) {
break;
}
cnt++;
node = node->Next;
} while (node != head);
if (compare(&value, &(node->Data))!=1) {
return (4);
}
else {
*pos = cnt;
return (3);
}
}
}
/*依次对链表中每个元素调用visit()*/
int TraverseList(List * list, int (*visit)(void *)) {
if (NULL == list) {
return (3); /*判断链表是否存在*/
}
else if (0 == list->Length) {
return (2); /*判断链表是否为空*/
}
else {
Node * head = list->Head;
Node * node = head;
do {
if (visit(&(node->Data))!=0) {
return (6);
}
node = node->Next;
} while (node != head); /*遍历链表,对各元素依次进行visit操作*/
return (0);
}
}
/*显示数字*/
int DisplayNumber(LIST_ELEM_TYPE * num) {
printf("%d ", *num);
return (0);
}
/*累加求和*/
long sum = 0;
int ComputeSum(LIST_ELEM_TYPE * num) {
sum += *num;
return (0);
}
/*记录最大数*/
int RecordLarger(LIST_ELEM_TYPE * num) {
if (*num > largest) {
largest = *num;
}
return (0);
}
/*对链表中每个元素就地逆置*/
int ReverseList(List * list) {
if (NULL == list) {
return (3); /*若链表不存在*/
}
else if (list->Length <= 1) {
return (0); /*若链表仅含有一个元素,则无需逆置*/
}
else if (list->Length == 2) {
list->Head = list->Head->Prior;
return (0); /*若链表含有两个元素,则将头指针后移即可*/
}
else {
Node * head = list->Head;
Node * tail = list->Head->Prior;
Node * node;
int i = 0;
int cnt = (list->Length)/2;
if (0 == (0x1 & (list->Length))) {
--cnt;
}
list->Head = list->Head->Prior; /*更新链表头指针位置*/
head->Next->Prior = tail;
tail->Prior->Next = head;
head->Prior = tail->Prior;
tail->Next = head->Next;
head->Next = tail;
tail->Prior = head; /*交换链表头尾节点指针关系*/
for (i = 1; i < cnt; i++) {
node = head;
head = tail->Next;
tail = node->Prior;
head->Next->Prior = tail;
head->Prior->Next = tail;
tail->Next->Prior = head;
tail->Prior->Next = head;
node = head->Next;
head->Next = tail->Next;
tail->Next = node;
node = head->Prior;
head->Prior = tail->Prior;
tail->Prior = node; /*交换链表中间非相邻节点指针关系*/
}
if (0 == (0x1 & (list->Length))) {
node = head;
head = tail->Next;
tail = node->Prior;
tail->Next->Prior = head;
head->Prior->Next = tail;
head->Next = tail->Next;
tail->Prior = head->Prior;
head->Prior = tail;
tail->Next = head; /*交换链表中间相邻节点指针关系*/
}
return (0);
}
}
/*程序功能菜单*/
char * mainMenu [] = {
"(1)Load The DoubleList",
"(2)Clear The Doublelist ",
"(3)Destroy The DoubleList",
"(4)Get The Length of The DoubleList",
"(5)Insert A Data",
"(6)Delete A Data According to the Position",
"(7)Delete A Data According to the Value",
"(8)Display All The Data",
"(9)Get the Max of the Data",
"(10)Get the average of the Data",
"(11)Reverse The DoubleList",
"(12)Exit",
NULL
};
/*从文件中载入线性表*/
int InputFromFile (char * filename, List * list) {
LIST_ELEM_TYPE num;
int i = 0;
FILE * fin = fopen(filename, "a+");
if (NULL == fin) {
printf("%s doesn't exist!The Data can't be loaded!\n", filename);
return (0);
}
else {
while (EOF != fscanf(fin, "%d", &num)) {
i++;
InsertElement(list, i, num);
}
return (0);
}
}
int main(void) {
int i;
int c;
List * list;
LIST_ELEM_TYPE num;
LIST_ELEM_TYPE num2;
list = CreateList();
InputFromFile("DoubleList.dat", list);
/*TraverseList(list, (int (*)(void *))DisplayNumber);*/
do {
i = 0;
printf("Welcome to the System!\n");
while (NULL != mainMenu[i]) {
printf(" %s\n", mainMenu[i]);
i++;
}
printf("Choose the type of Operation:");
scanf("%d", &c);
switch (c) {
/*(1)载入线性表*/
case 1:
DisposeList(list);
list = CreateList();
if ((InputFromFile("DoubleList.dat",list))==0) {
printf("The DoubleList has been loaded,there are %d of data in total.\n", ListLength(list));
}
break;
/*(2)线性表置空*/
case 2:
if (NULL == list) {
printf("The DoubleList doesn't exist!\n");
}
else {
ClearList(list);
printf("The DoubleList has been cleared!\n");
}
break;
/*(3)销毁线性表*/
case 3:
DisposeList(list);
list = NULL;
printf("The DoubleList has been destroyed!\n");
break;
/*(4)获取线性表长度*/
case 4:
if (NULL == list) {
printf("The DoubleList doesn't exist!\n");
}
else {
i = ListLength(list);
if (0 == i) {
printf("The DoubleList is empty\n");
}
else {
printf("The length of the list is %d\n", i);
}
}
break;
/*(5)插入数据元素*/
case 5:
if (NULL == list) {
printf("The DoubleList doesn't exist\n");
}
else {
printf("The position of the inserted data:");
scanf("%d", &i);
printf("The value of the inserted data:");
scanf("%d", &num);
if (InsertElement(list, i, num)==0) {
printf("Successfully inserted\n");
}
else {
printf("Fail to insert!\n");
}
}
break;
/*(6)删除位置数据元素*/
case 6:
if (NULL == list) {
printf("The DoubleList doesn't exist\n");
}
else {
printf("The position of the deleted data:");
scanf("%d", &i);
if ( DeleteElement(list, i, &num)==0) {
printf("Successfully deleted!\n", num);
}
else {
printf("Fail to delete!\n");
}
}
break;
/*(7)删除数值数据元素*/
case 7:
if (NULL == list) {
printf("The DoubleList doesn't exist\n");
}
else {
printf("The value of the deleted data:");
scanf("%d", &num);
if (DeleteData(list, num)==0) {
printf("Successfully deleted!\n", num);
}
else {
printf("Fail to delete!\n");
}
}
break;
/*(8)显示全部数据元素*/
case 8:
if (NULL == list) {
printf("The DoubleList doesn't exist!\n");
}
else if ( IsListEmpty(list)==1) {
printf("The DoubleList is empty!\n");
}
else {
printf("Display the DoubleList:");
TraverseList(list, (int (*)(void *))DisplayNumber);
printf("\n");
}
break;
/*(9)求最大元素*/
case 9:
if (NULL == list) {
printf("The DoubleList doesn't exist!\n");
}
else if (0 == ListLength(list)) {
printf("The DoubleList is empty!\n");
}
else {
largest =1;
TraverseList(list, (int (*)(void *))RecordLarger);
printf("The max of the data is:%d\n", largest);
}
break;
/*(10)求所有元素平均值*/
case 10:
if (NULL == list) {
printf("The DoubleList doesn't exist!\n");
}
else if (0 == (i = ListLength(list))) {
printf("The DoubleList is empty!\n");
}
else {
sum = 0;
TraverseList(list, (int (*)(void *))ComputeSum);
printf("The Length of the list is:%d\n",i);
printf("The sum of all the data is %d\n",sum);
printf("The average is %f\n",((double)sum)/((double)i));
}
break;
/*(11)就地置逆线性表*/
case 11:
if (NULL == list) {
printf("The DoubleList doesn't exist!\n");
}
else {
ReverseList(list);
printf("The DoubleList has been reversed\n");
}
break;
/*(12)退出程序*/
case 12:
printf("ByeBye!\n");
break;
default:
printf("The operation doesn't exist!\n");
break;
}
getchar();
getchar();
} while (c!= 12);
return (0);
}