双链表
目的:双链表的存储结构和掌握双链表中各种基本运算算法的设计
内容:编写一个程序dlinkst.cpp,实现双链表的各种基本运算和整体建表算法,双链表的元素类型Elem Type为int并在此基础上设计一个程序。
(1)初始化双链表h。
(2)依次采用尾插法插人a、b、c、d、e元素。
(3)输出双链表h。
(4)输出双链表h的长度。
(5)判断双链表h是否为空。
(6)输出双链表h的第3个元素。
(7)输出元素a的位置。
(8)在第4个元素的位置上插入f元素。
(9)输出双链表h。
(10)删除双链表h的第3个元素。
(11)输出双链表h。
(12)释放双链表h。
#include <stdio.h>
#include <stdlib.h>// 定义双链表节点结构
typedef struct DListNode {int data;struct DListNode *prev, *next;
} DListNode;// 定义双链表结构
typedef struct DLinkList {DListNode *head;
} DLinkList;// 初始化双链表
void InitList(DLinkList *L) {L->head = NULL;
}// 创建新节点
DListNode *CreateNode(int value) {DListNode *newNode = (DListNode *)malloc(sizeof(DListNode));if (newNode == NULL) {printf("Memory allocation failed.\n");exit(-1);}newNode->data = value;newNode->prev = NULL;newNode->next = NULL;return newNode;
}// 插入尾部元素
void InsertTail(DLinkList *L, int value) {DListNode *newNode = CreateNode(value);//先创建这个结点if (L->head == NULL) {L->head = newNode;//头结点若为空,说明目前没元素,所以只需把新结点放在//头结点后面即可} else {DListNode *curr = L->head;while (curr->next != NULL) {curr = curr->next;}curr->next = newNode;newNode->prev = curr;//若头结点不为空,先创建一个指针从头结点开始一直遍历到尾结点//再将新结点放在尾结点后,新结点的prior设置为尾结点}
}// 输出双链表
void PrintList(DLinkList *L) {DListNode *curr = L->head;while (curr != NULL) {printf("%c ", curr->data);curr = curr->next;}printf("\n");//从头结点的后一个节点开始遍历链表
}// 获取双链表长度
int Length(DLinkList *L) {int count = 0;DListNode *curr = L->head;while (curr != NULL) {count++;curr = curr->next;}return count;//同样遍历链表即可
}// 判断双链表是否为空
int IsEmpty(DLinkList *L) {return L->head == NULL;//头结点后面没结点说明链表为空
}// 获取指定位置的元素
int GetElement(DLinkList *L, int pos) {if (pos < 0 || pos >= Length(L)) return -1;//位置不合法DListNode *curr = L->head;for (int i = 0; i < pos; ++i) {curr = curr->next;}//for循环找到对应位置return curr->data;
}// 查找元素的位置
int FindElement(DLinkList *L, int value) {DListNode *curr = L->head;int pos = 0;while (curr != NULL) {if (curr->data == value) return pos;curr = curr->next;pos++;}//同样是循环,不断匹配value,匹配成功就返回位置posreturn -1;
}// 在指定位置插入元素
void InsertAt(DLinkList *L, int pos, int value) {if (pos < 0 || pos > Length(L)) return;//位置不合法DListNode *newNode = CreateNode(value);//创建这个元素的结点if (pos == 0) {newNode->next = L->head;if (L->head != NULL) L->head->prev = newNode;L->head = newNode;//插入结点} else {DListNode *curr = L->head;for (int i = 0; i < pos - 1; ++i) {curr = curr->next;}newNode->next = curr->next;newNode->prev = curr;if (curr->next != NULL) curr->next->prev = newNode;//若插入的这个节点的位置不是尾结点curr->next = newNode;//位置是尾结点的情况}
}// 删除指定位置的元素
void DeleteAt(DLinkList *L, int pos) {if (pos < 0 || pos >= Length(L)) return;//位置不合法DListNode *curr = L->head;if (pos == 0) {L->head = L->head->next;if (L->head != NULL) L->head->prev = NULL;//若头结点后面有结点,就让头结点指向空} else {for (int i = 0; i < pos; ++i) {curr = curr->next;}curr->prev->next = curr->next;if (curr->next != NULL) curr->next->prev = curr->prev;//删除结点}free(curr);
}// 清空链表
void ClearList(DLinkList *L) {while (L->head != NULL) {DListNode *temp = L->head;L->head = L->head->next;free(temp);}
}int main() {DLinkList h;InitList(&h);// (2) 依次采用尾插法插入a、b、c、d、e元素。InsertTail(&h, 'a');InsertTail(&h, 'b');InsertTail(&h, 'c');InsertTail(&h, 'd');InsertTail(&h, 'e');// (3) 输出双链表h。printf("(3) 输出双链表h:");PrintList(&h);// (4) 输出双链表h的长度。printf("(4) 输出双链表h的长度: %d\n", Length(&h));// (5) 判断双链表h是否为空。printf("(5)判断双链表h是否为空: %s\n", IsEmpty(&h) ? "Yes" : "No");// (6) 输出双链表h的第3个元素。printf("(6) 输出双链表h的第3个元素: %c\n", GetElement(&h, 2));// (7) 输出元素a的位置。printf("(7) 输出元素a的位置: %d\n", FindElement(&h, 'a'));// (8) 在第4个元素的位置上插入f元素。InsertAt(&h, 3, 'f');printf("(8) 在第4个元素的位置上插入f元素:");PrintList(&h);// (9) 输出双链表h。printf("(9) 输出双链表h:");PrintList(&h);// (10) 删除双链表h的第3个元素。DeleteAt(&h, 2);printf("(10) 删除双链表h的第3个元素:");PrintList(&h);// (11) 输出双链表h。printf("(11) 输出双链表h:");PrintList(&h);// (12) 释放双链表h。ClearList(&h);return 0;
}
循环链表
实验题:实现循环双链表的各种基本运算的算法目的:领会循环双链表的存储结构和掌握循环双链表中各种基本运算算法的设计。
内容:编写一个程序cdlinklist..cpp,实现循环双链表的各种基本运算和整体建表算法(假设循环双链表的元素类型ElemType为int),完成以下功能。
(1)初始化循环双链表h。
(2)依次采用尾插法插入a、b、c、d、e元素。
(3)输出循环双链表h。
(4)输出循环双链表h的长度。
(5)判断循环双链表h是否为空。
(6)输出循环双链表h的第3个元素。
(7)输出元素a的位置。
(8)在第4个元素的位置上插入f元素。
(9)输出循环双链表h。
(10)删除循环双链表h的第3个元素。
(11)输出循环双链表h。
(12)释放循环双链表h。
#include <stdio.h>
#include <stdlib.h>// 定义循环双链表节点结构
typedef struct CDListNode {int data;struct CDListNode *prior, *next;
} CDListNode;// 定义循环双链表结构
typedef struct CDLinkList {CDListNode *head;//头结点
} CDLinkList;// 初始化循环双链表
void InitList(CDLinkList *L) {L -> head = NULL;//初始化头结点为空
}// 创建新节点
CDListNode *CreateNode(int value) {CDListNode *newNode = (CDListNode *)malloc(sizeof(CDListNode));newNode -> data = value;newNode -> prior = newNode -> next = NULL;//将新结点的prior和next初始化为空return newNode;
}// 插入尾部元素
void InsertTail(CDLinkList *L, int value) {CDListNode *newNode = CreateNode(value);if (L -> head == NULL) {L -> head = newNode;newNode -> prior = newNode -> next = newNode; // 形成循环,让尾结点的next指向头结点} else {CDListNode *tail = L -> head -> prior;//创建tail指针指向尾结点tail -> next = newNode;newNode -> prior = tail;//将新结点放在尾结点后面newNode -> next = L -> head;L -> head -> prior = newNode;//让新结点的next指向头结点,头结点的next指向新结点//形成循环}
}// 输出循环双链表
void PrintList(CDLinkList *L) {if (L -> head == NULL) {printf("循环链表为空\n");return;}//头结点为空代表循环链表为空CDListNode *curr = L -> head;do {printf("%c ", curr->data);curr = curr -> next;} while (curr != L->head);//do while循环遍历循环链表printf("\n");
}// 获取循环双链表长度
int Length(CDLinkList *L) {int count = 0;CDListNode *curr = L->head;if (curr == NULL) return 0;do {count++;curr = curr->next;} while (curr != L->head);//同样循环遍历,每次让count++,得到链表长度return count;
}// 判断循环双链表是否为空
int IsEmpty(CDLinkList *L) {return L->head == NULL;//若头结点为空则链表为空
}// 获取指定位置的元素
int GetElement(CDLinkList *L, int pos) {if (pos < 0 || pos >= Length(L)) return -1;//长度不合法直接返回CDListNode *curr = L -> head;int index = 0;do {if (index == pos) return curr -> data;//只要循环到指定位置就返回对应值,否则继续循环curr = curr -> next;index++;} while (curr != L->head);return -1;
}// 查找元素的位置
int FindElement(CDLinkList *L, int value) {CDListNode *curr = L -> head;int pos = 0;if (curr == NULL) return -1;//链表为空,无需查找,直接返回do {if (curr -> data == value) return pos;//循环不断匹配数值,相同则返回它的位置curr = curr -> next;pos++;} while (curr != L -> head);return -1;
}// 在指定位置插入元素
void InsertAt(CDLinkList *L, int pos, int value) {if (pos < 0 || pos > Length(L)) return;//位置不合法直接返回CDListNode *newNode = CreateNode(value);//创建要插入的那个结点if (pos == 0) {//pos为0表示要插入在头结点后面newNode -> next = L -> head;newNode -> prior = L -> head -> prior;//将新结点插入到头结点后L -> head -> prior -> next = newNode;L -> head -> prior = newNode;L -> head = newNode;//形成循环} else {CDListNode *curr = L -> head;int index = 0;do {if (index == pos - 1) break;curr = curr -> next;index++;} while (curr != L -> head);//找到要插入结点的位置newNode -> next = curr -> next;newNode -> prior = curr;curr -> next -> prior = newNode;curr -> next = newNode;//插入结点}
}// 删除指定位置的元素
void DeleteAt(CDLinkList *L, int pos) {if (pos < 0 || pos >= Length(L)) return;//位置不合法直接返回CDListNode *curr = L -> head;int index = 0;if (pos == 0) {L -> head -> prior -> next = L -> head -> next;L -> head -> next -> prior = L -> head -> prior;L -> head = L -> head ->next;free(curr);//删除第一个结点的情况} else {do {if (index == pos) break;curr = curr -> next;index++;} while (curr != L->head);//找到要删除的结点的位置curr -> prior -> next = curr -> next;curr -> next -> prior = curr -> prior;free(curr);//删除结点}
}// 清空链表
void ClearList(CDLinkList *L) {while (L -> head != NULL) {CDListNode *temp = L -> head;L -> head = L -> head -> next;free(temp);}L -> head = NULL;//释放头结点,并且将头结点的指针设置为空实现清空链表
}int main() {CDLinkList h;//初始化循环双链表InitList(&h);// (2) 依次采用尾插法插入a、b、c、d、e元素。InsertTail(&h, 'a');InsertTail(&h, 'b');InsertTail(&h, 'c');InsertTail(&h, 'd');InsertTail(&h, 'e');// (3) 输出循环双链表h。printf("(3) 输出循环双链表h:");PrintList(&h);// (4) 输出循环双链表h的长度。printf("(4) 输出循环双链表h的长度: %d\n", Length(&h));// (5) 判断循环双链表h是否为空。printf("(5) 判断循环双链表h是否为空: %s\n", IsEmpty(&h) ? "Yes" : "No");// (6) 输出循环双链表h的第3个元素。printf("(6) 输出循环双链表h的第3个元素: %c\n", GetElement(&h, 2));// (7) 输出元素a的位置。printf("(7) 输出元素a的位置: %d\n", FindElement(&h, 'a'));// (8) 在第4个元素的位置上插入f元素。InsertAt(&h, 3, 'f');// (9) 输出循环双链表h。printf("(9) 输出循环双链表h:");PrintList(&h);// (10) 删除循环双链表h的第3个元素。DeleteAt(&h, 2);// (11) 输出循环双链表h。printf("(11) 输出循环双链表h:");PrintList(&h);// (12) 释放循环双链表h。ClearList(&h);return 0;
}