目录
一.双链表
双链表对比于单链表添加了一个前驱指针域,优势是可以实现双向遍历,而单链表只能从头结点开始遍历。
学生作业,大佬路过有误请指正。
二.代码展示
1.双向链表的定义
/**
* Double linked list of integers. The key is char.
*/
typedef struct DoubleLinkedNode{
char data;
struct DoubleLinkedNode *prior;
struct DoubleLinkedNode *next;
}DLNode, *DLNodePtr;
2.双向链表的初始化
/**
* Initialize the list with a header.
* @return The pointer to the header.
*/
DLNodePtr initLinkList(){
DLNodePtr tempHeader=(DLNodePtr)malloc(sizeof(DLNode));
tempHeader->data='\0';
tempHeader->next=NULL;
tempHeader->prior=NULL;
return tempHeader;
}
3.双向链表在指定位置插入新元素
图形展示
/**
* Insert an element to the given position.
* @param paraHeader The header of the list.
* @param paraChar The given char.
* @param paraPosition The given position.
*/
void insertElement(DLNodePtr paraHeader, char paraChar, int paraPosition){
DLNodePtr p,q,r;
p=paraHeader;
//step 1. create the Element Node;
q = (DLNodePtr)malloc(sizeof(DLNodePtr));
q->data=paraChar;
//step 2. search the position
for(int i=0;i<paraPosition;i++){
p=p->next;
if (p == NULL) {
printf("The position %d is beyond the scope of the list.\r\n", paraPosition);
return;
}
}
// Step 3. Now link.
q->prior=p;
q->next=p->next;
p->next=q;
if(q->next!=NULL){
q->next->prior=q;
}
}
4.双向链表删除指定元素
图形展示
/**
* Delete an element from the list.
* @param paraHeader The header of the list.
* @param paraChar The given char.
*/
void deleteElement(DLNodePtr paraHeader, char paraChar){
DLNodePtr p,q;
p=paraHeader;
//step 1. search the paraChar.
while(p->data!=paraChar){
p=p->next;
if(p==NULL){
printf("The Element %c is not search.\r\n", paraChar);
return;
}
}
//srep 2. delete the Node.
q=p->prior;
q->next=p->next;
if(p->next!=NULL){
p->next->prior=q;
}
free(p);
}
5.找到指定元素的位置
/**
* Locate an element in the list.
* @param paraHeaderPtr The pointer to the list.
* @param paraValue the indicated value.
* @return The position of the value, or -1 indicating not exists
*/
int locateElement(DLNodePtr paraHeader, char paraValue){
DLNodePtr p=paraHeader;
for(int i=0; ;i++){
if(p->data==paraValue){
return i;
}
p=p->next;
}
return -1;
}
6.打印链表长度
/**
* count the length in the list.
* @param paraHeaderPtr The pointer to the list.
*/
void lengthDLList(DLNodePtr paraHeader){
DLNodePtr p=paraHeader;
int i;
for(i=0;p->next!=NULL;i++){
p=p->next;
}
printf("Length=%d\r\n",i);
}
7.双向链表的整表删除
/**
* clear the list.
* @param paraHeader The header of the list.
*/
void clearDL(DLNodePtr paraHeader){
DLNodePtr p,q;
p=paraHeader->next;
while(p){
q=p->next;
free(p);
p=q;
}
paraHeader=NULL;
}
8.返回指定结点的地址
/**
* Address test: beyond the book.
*/
void basicAddressTest(){
DLNode tempNode1, tempNode2;
tempNode1.data = 4;
tempNode1.next = NULL;
tempNode2.data = 6;
tempNode2.next = NULL;
printf("The first node: %d, %d, %d\r\n",
&tempNode1, &tempNode1.data, &tempNode1.next);
printf("The second node: %d, %d, %d\r\n",
&tempNode2, &tempNode2.data, &tempNode2.next);
tempNode1.next = &tempNode2;
}
9.完整代码
#include <stdio.h>
#include <malloc.h>
/**
* Double linked list of integers. The key is char.
*/
typedef struct DoubleLinkedNode{
char data;
struct DoubleLinkedNode *prior;
struct DoubleLinkedNode *next;
}DLNode, *DLNodePtr;
/**
* Initialize the list with a header.
* @return The pointer to the header.
*/
DLNodePtr initLinkList(){
DLNodePtr tempHeader=(DLNodePtr)malloc(sizeof(DLNode));
tempHeader->data='\0';
tempHeader->next=NULL;
tempHeader->prior=NULL;
return tempHeader;
}
/**
* Print the list.
* @param paraHeader The header of the list.
*/
void printList(DLNodePtr paraHeader){
DLNodePtr p;
p=paraHeader->next;
while(p!=NULL)
{
printf("%c",p->data);
p=p->next;
}
printf("\r\n");
}
/**
* Insert an element to the given position.
* @param paraHeader The header of the list.
* @param paraChar The given char.
* @param paraPosition The given position.
*/
void insertElement(DLNodePtr paraHeader, char paraChar, int paraPosition){
DLNodePtr p,q,r;
p=paraHeader;
//step 1. create the Element Node;
q = (DLNodePtr)malloc(sizeof(DLNodePtr));
q->data=paraChar;
//step 2. search the position
for(int i=0;i<paraPosition;i++){
p=p->next;
if (p == NULL) {
printf("The position %d is beyond the scope of the list.\r\n", paraPosition);
return;
}
}
// Step 3. Now link.
q->prior=p;
q->next=p->next;
p->next=q;
if(q->next!=NULL){
q->next->prior=q;
}
}
/**
* Delete an element from the list.
* @param paraHeader The header of the list.
* @param paraChar The given char.
*/
void deleteElement(DLNodePtr paraHeader, char paraChar){
DLNodePtr p,q;
p=paraHeader;
//step 1. search the paraChar.
while(p->data!=paraChar){
p=p->next;
if(p==NULL){
printf("The Element %c is not search.\r\n", paraChar);
return;
}
}
//srep 2. delete the Node.
q=p->prior;
q->next=p->next;
if(p->next!=NULL){
p->next->prior=q;
}
free(p);
}
/**
* Locate an element in the list.
* @param paraHeaderPtr The pointer to the list.
* @param paraValue the indicated value.
* @return The position of the value, or -1 indicating not exists
*/
int locateElement(DLNodePtr paraHeader, char paraValue){
DLNodePtr p=paraHeader;
for(int i=0; ;i++){
if(p->data==paraValue){
return i;
}
p=p->next;
}
return -1;
}
/**
* count the length in the list.
* @param paraHeaderPtr The pointer to the list.
*/
void lengthDLList(DLNodePtr paraHeader){
DLNodePtr p=paraHeader;
int i;
for(i=0;p->next!=NULL;i++){
p=p->next;
}
printf("Length=%d\r\n",i);
}
/**
* clear the list.
* @param paraHeader The header of the list.
*/
void clearDL(DLNodePtr paraHeader){
DLNodePtr p,q;
p=paraHeader->next;
while(p){
q=p->next;
free(p);
p=q;
}
paraHeader=NULL;
}
void insertDeleteLocateLengthTest(){
// Step 1. Initialize an empty list.
DLNodePtr tempList = initLinkList();
printList(tempList);
// Step 2. Add some characters.
insertElement(tempList, 'C', 0);
insertElement(tempList, 'Y', 1);
insertElement(tempList, 'H', 2);
insertElement(tempList, 'Z', 3);
insertElement(tempList, 'S', 4);
insertElement(tempList, '!', 5);
printList(tempList);
// Step 3. Delete some characters (the first occurrence).
deleteElement(tempList, 'C');
deleteElement(tempList, 'Z');
deleteElement(tempList, 'O');
printList(tempList);
// Step 4. Insert to a given position.
insertElement(tempList, 'C', 0);
insertElement(tempList, 'Z', 3);
insertElement(tempList, 'C', 7);
printList(tempList);
//step 5.locate the Elemment.
printf("C在第%d位\r\n",locateElement(tempList,'C'));
printf("Z在第%d位\r\n",locateElement(tempList,'Z'));
//step 6.count the List length
lengthDLList(tempList);
}
/**
* Address test: beyond the book.
*/
void basicAddressTest(){
DLNode tempNode1, tempNode2;
tempNode1.data = 4;
tempNode1.next = NULL;
tempNode2.data = 6;
tempNode2.next = NULL;
printf("The first node: %d, %d, %d\r\n",
&tempNode1, &tempNode1.data, &tempNode1.next);
printf("The second node: %d, %d, %d\r\n",
&tempNode2, &tempNode2.data, &tempNode2.next);
tempNode1.next = &tempNode2;
}
/**
* The entrance.
*/
int main(){
insertDeleteLocateLengthTest();
basicAddressTest();
}
10.样例测试输出
CYHZS!
The Element O is not search.
YHS!
The position 7 is beyond the scope of the list.
CYHZS!
C在第1位
Z在第4位
Length=6
The first node: 6487504, 6487504, 6487520
The second node: 6487472, 6487472, 6487488
三.总结
双向链表和单链表的基本操作差不多类似,只是可以通过当前结点找到前驱结点,而不像单链表只能找到后继结点。找前驱结点不用再遍历一次链表,通过增加空间复杂度来换取时间复杂度。
但是双向链表使用的地方并不多,单链表使用的情况比较多一点。
四.附上老师的代码
#include <stdio.h>
#include <malloc.h>
/**
* Linked list of characters. The key is data.
*/
typedef struct LinkNode{
char data;
struct LinkNode *next;
} LNode, *LinkList, *NodePtr;
/**
* Initialize the list with a header.
* @return The pointer to the header.
*/
LinkList initLinkList(){
NodePtr tempHeader = (NodePtr)malloc(sizeof(LNode));
tempHeader->data = '\0';
tempHeader->next = NULL;
return tempHeader;
}
/**
* Print the list.
* @param paraHeader The header of the list.
*/
void printList(NodePtr paraHeader){
NodePtr p = paraHeader->next;
while (p != NULL) {
printf("%c", p->data);
p = p->next;
}
printf("\r\n");
}
/**
* Add an element to the tail.
* @param paraHeader The header of the list.
* @param paraChar The given char.
*/
void appendElement(NodePtr paraHeader, char paraChar){
NodePtr p, q;
// Step 1. Construct a new node.
q = (NodePtr)malloc(sizeof(LNode));
q->data = paraChar;
q->next = NULL;
// Step 2. Search to the tail.
p = paraHeader;
while (p->next != NULL) {
p = p->next;
}
// Step 3. Now add/link.
p->next = q;
}
/**
* Insert an element to the given position.
* @param paraHeader The header of the list.
* @param paraChar The given char.
* @param paraPosition The given position.
*/
void insertElement(NodePtr paraHeader, char paraChar, int paraPosition){
NodePtr p, q;
// Step 1. Search to the position.
p = paraHeader;
for (int i = 0; i < paraPosition; i ++) {
p = p->next;
if (p == NULL) {
printf("The position %d is beyond the scope of the list.", paraPosition);
return;
}
} /
// Step 2. Construct a new node.
q = (NodePtr)malloc(sizeof(LNode));
q->data = paraChar;
// Step 3. Now link.
printf("linking\r\n");
q->next = p->next;
p->next = q;
}
/**
* Delete an element from the list.
* @param paraHeader The header of the list.
* @param paraChar The given char.
*/
void deleteElement(NodePtr paraHeader, char paraChar){
NodePtr p, q;
p = paraHeader;
while ((p->next != NULL) && (p->next->data != paraChar)){
p = p->next;
}
if (p->next == NULL) {
printf("Cannot delete %c\r\n", paraChar);
return;
}/
q = p->next;
p->next = p->next->next;
free(q);
}
/**
* Unit test.
*/
void appendInsertDeleteTest(){
// Step 1. Initialize an empty list.
LinkList tempList = initLinkList();
printList(tempList);
// Step 2. Add some characters.
appendElement(tempList, 'H');
appendElement(tempList, 'e');
appendElement(tempList, 'l');
appendElement(tempList, 'l');
appendElement(tempList, 'o');
appendElement(tempList, '!');
printList(tempList);
// Step 3. Delete some characters (the first occurrence).
deleteElement(tempList, 'e');
deleteElement(tempList, 'a');
deleteElement(tempList, 'o');
printList(tempList);
// Step 4. Insert to a given position.
insertElement(tempList, 'o', 1);
printList(tempList);
}
/**
* Address test: beyond the book.
*/
void basicAddressTest(){
LNode tempNode1, tempNode2;
tempNode1.data = 4;
tempNode1.next = NULL;
tempNode2.data = 6;
tempNode2.next = NULL;
printf("The first node: %d, %d, %d\r\n",
&tempNode1, &tempNode1.data, &tempNode1.next);
printf("The second node: %d, %d, %d\r\n",
&tempNode2, &tempNode2.data, &tempNode2.next);
tempNode1.next = &tempNode2;
}
/**
* The entrance.
*/
int main(){
appendInsertDeleteTest();
}