双向循环链表(C语言描述)(三)

代码清单

  1 // linkedlist.h
  2 #ifndef __LINKEDLIST_H__
  3 #define __LINKEDLIST_H__
  4
  5 #include <assert.h>
  6 #include <malloc.h>
  7 #include <string.h>
  8
  9 typedef int LinkedListData;
 10
 11 typedef struct LinkedListNode {
 12     LinkedListData data;
 13
 14     struct LinkedListNode * prior;
 15     struct LinkedListNode * next;
 16 } LinkedListNode, *LinkedList;
 17
 18 typedef enum {
 19     TRAVELDIR_FORWARD, TRAVELDIR_BACKWARD
 20 } LinkedListTravelDir;
 21
 22 LinkedList linkedlist_new();
 23 void linkedlist_destory(LinkedList *list);
 24
 25 void linkedlist_insert(LinkedList list, LinkedListTravelDir dir, int location,
 26         const LinkedListData data);
 27 void linkedlist_delete(LinkedList list, LinkedListTravelDir dir, int location);
 28 int linkedlist_locate(const LinkedList list, LinkedListTravelDir dir,
 29         const LinkedListData data, int (*fpCompare)(const void *, const void *));
 30 LinkedListData * linkedlist_get(LinkedList list, LinkedListTravelDir dir,
 31         int location);
 32 int linkedlist_length(const LinkedList list);
 33
 34 #endif // __LINKEDLIST_H__
 35
 36 // linkedlist.c
 37 #include "linkedlist.h"
 38
 39 LinkedList linkedlist_new() {
 40     // alloc head node
 41     LinkedList list = malloc(sizeof(LinkedListNode));
 42     assert(list);
 43
 44     // initialize head node‘s pointer field
 45     list->prior = list;
 46     list->next = list;
 47
 48     return list;
 49 }
 50
 51 void linkedlist_destory(LinkedList *list) {
 52     while (linkedlist_length(*list)) {
 53         linkedlist_delete(*list, TRAVELDIR_FORWARD, 1);
 54     }
 55     free (*list);
 56     *list = NULL;
 57 }
 58
 59 void linkedlist_insert(LinkedList list, LinkedListTravelDir dir, int location,
 60         const LinkedListData data) {
 61     LinkedList pCurNode = list;
 62     assert(location > 0 && location <= linkedlist_length(list) + 1);
 63
 64     // alloc new node
 65     LinkedListNode * pNode = malloc(sizeof(LinkedListNode));
 66     assert(pNode);
 67     memcpy(&(pNode->data), &data, sizeof(LinkedListData));
 68
 69     // move current pointer to prior node
 70     if (dir == TRAVELDIR_FORWARD) {
 71         for (int i = 0; i < location - 1; i++, pCurNode = pCurNode->next)
 72             ;
 73
 74     } else {
 75         if (dir == TRAVELDIR_BACKWARD) {
 76             for (int i = 0; i < location; i++, pCurNode = pCurNode->prior)
 77                 ;
 78         }
 79     }
 80
 81     // insert new node
 82     pNode->next = pCurNode->next;
 83     pNode->prior = pCurNode;
 84     pCurNode->next = pNode;
 85     pNode->next->prior = pNode;
 86 }
 87
 88 void linkedlist_delete(LinkedList list, LinkedListTravelDir dir, int location) {
 89     LinkedList pCurNode = list;
 90     assert(location > 0 && location < linkedlist_length(list) + 1);
 91
 92     // move current pointer to the node will deleted
 93     if (dir == TRAVELDIR_FORWARD) {
 94         for (int i = 0; i < location; i++, pCurNode = pCurNode->next)
 95             ;
 96     } else {
 97         if (dir == TRAVELDIR_BACKWARD) {
 98             for (int i = 0; i < location; i++, pCurNode = pCurNode->prior)
 99                 ;
100         }
101     }
102
103     // delete current node
104     pCurNode->prior->next = pCurNode->next;
105     pCurNode->next->prior = pCurNode->prior;
106     free(pCurNode);
107 }
108
109 int linkedlist_locate(const LinkedList list, LinkedListTravelDir dir,
110         const LinkedListData data, int (*fpCompare)(const void *, const void *)) {
111     static int location = 0;
112     static LinkedList pCurNode = NULL;
113
114     // if list argument is NULL, continue to start locate
115     if (list) {
116         location = 1;
117         pCurNode = list->next;
118     }
119     assert(location && pCurNode);
120
121     // locate data
122     while (pCurNode != list) {
123         if (!fpCompare(&(pCurNode->data), &data)) {
124             return location;
125         }
126         location++;
127         if (dir == TRAVELDIR_FORWARD) {
128             pCurNode = pCurNode->next;
129         } else {
130             if (dir == TRAVELDIR_BACKWARD) {
131                 pCurNode = pCurNode->prior;
132             }
133         }
134     }
135
136     return -1;
137 }
138
139 LinkedListData * linkedlist_get(LinkedList list, LinkedListTravelDir dir,
140         int location) {
141     LinkedList pCurNode = list;
142     assert(location > 0 && location < linkedlist_length(list) + 1);
143
144     // move pointer to the node wanna get
145     if (dir == TRAVELDIR_FORWARD) {
146         for (int i = 0; i < location; i++, pCurNode = pCurNode->next)
147             ;
148     } else {
149         if (dir == TRAVELDIR_BACKWARD) {
150             for (int i = 0; i < location; i++, pCurNode = pCurNode->prior)
151                 ;
152         }
153     }
154
155     return &(pCurNode->data);
156 }
157
158 int linkedlist_length(const LinkedList list) {
159     int length = 0;
160     assert(list);
161     LinkedList pCurNode = list->next;
162
163     while (pCurNode != list) {
164         length++;
165         pCurNode = pCurNode->next;
166     }
167
168     return length;
169 }
时间: 2024-08-04 19:57:14

双向循环链表(C语言描述)(三)的相关文章

双向循环链表-C语言版

源文件部分: #include<stdio.h> #include<string.h> #include<malloc.h> typedef int Elemtype; #include"Delist.h" int main() { Dlnode head=NULL; instruction(head); return 0; } 头文件部分: typedef struct DLnode { Elemtype data; struct DLnode *

双向循环链表(C语言描述)(四)

下面以一个电子英汉词典程序(以下简称电子词典)为例,应用双向循环链表.分离数据结构,可以使逻辑代码独立于数据结构操作代码,程序结构更清晰,代码更简洁:电子词典的增.删.查.改操作分别对应于链表的插入.删除.查找.查找和获取链表元素操作. 在程序初始化时,除了初始化链表,还要将保存在文件中的词库加载到链表中: 1 void dict_init() { 2 list = linkedlist_new(); 3 4 dict_load(); 5 printf("Welcome."); 6 }

C语言通用双向循环链表操作函数集

说明 相比Linux内核链表宿主结构可有多个链表结构的优点,本函数集侧重封装性和易用性,而灵活性和效率有所降低.     可基于该函数集方便地构造栈或队列集.     本函数集暂未考虑并发保护. 一  概念 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序通过链表中的指针链接次序实现.链表由一系列存储结点组成,结点可在运行时动态生成.每个结点均由两部分组成,即存储数据元素的数据域和存储相邻结点地址的指针域.当进行插入或删除操作时,链表只需修改相关结点的指针域即可,因此相比线性

数据结构与问题求解-Java语言描述(第三版)

数据结构对程序的重要性不言而喻,用java语言来实现常见的一些数据结构,以及在相应数据结构上的操作对学习java的同学来说是必须掌握的. 本系列博文参考<数据结构与问题求解-Java语言描述(第三版)>来实现 在自己学习的过程中,更希望有机会与大家交流. PS :本人是菜鸟,只是用博客的方式激励自己.请轻喷.Fighting!

C语言双向循环链表api(源自gluster源码)

C语言双向循环链表api(源自gluster源码)基本的操作如增加.删除和遍历等 #include <stdio.h> #include <stdlib.h> #include <string.h> /*定义表头*/ struct list_head { struct list_head *next; struct list_head *prev; }; /*表头初始化*/ #define INIT_LIST_HEAD(head) do { (head)->nex

c语言编程之双向循环链表

双向循环链表就是形成两个环,注意每个环的首尾相连基本就可以了. 程序中采用尾插法进行添加节点. 1 #include<stdio.h> 2 #include<stdlib.h> 3 #define element int 4 typedef struct Node{ 5 element data; 6 struct Node *next; 7 struct Node *prior; 8 }*pNode; 9 10 //build a new double loop list 11

c语言双向循环链表

双向循环链表,先来说说双向链表,双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点.而循环链表之前也有说过,单链表中就是让最后一个结点的指针指向第一个结点就能构成一个循环链表,这里其实也是一样的,只不过多了一步,让第一个结点的前驱指向最后一个结点就行了,(这里介绍的是带头结点的双向循环链表,所以用第一个结点和头结点来区分两者).下面直接看看怎么创建一个带头结点的双向循环链表吧

C语言双向循环链表实现及图示(初始化/插入链表/清空/销毁)

-------------------------------------------- 双向循环链表 //遍历等执行方法与普通双向链表相同,不单独列举 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 初始化+尾插法 图示: 实现代码 1 /* 初始化

数据结构8: 双向链表(双向循环链表)的建立及C语言实现

之前接触到的链表都只有一个指针,指向直接后继,整个链表只能单方向从表头访问到表尾,这种结构的链表统称为 “单向链表”或“单链表”. 如果算法中需要频繁地找某结点的前趋结点,单链表的解决方式是遍历整个链表,增加算法的时间复杂度,影响整体效率.为了快速便捷地解决这类问题,在单向链表的基础上,给各个结点额外配备一个指针变量,用于指向每个结点的直接前趋元素.这样的链表被称为“双向链表”或者“双链表”. 双链表中的结点 双向链表中的结点有两个指针域,一个指向直接前趋,一个指向直接后继.(链表中第一个结点的

第三十三课 双向循环链表的实现

头结点不位于链表里面,只是用于定位,和内核链表不同. 将LinuxList.h添加到我们的工程中. 再添加一个DualCircleList.h文件: 1 #ifndef DUALCIRCLELIST_H 2 #define DUALCIRCLELIST_H 3 4 #include "LinuxList.h" 5 #include "DualLinkList.h" 6 7 namespace DTLib 8 { 9 10 template < typename