C语言实现双向非循环链表(不带头结点)的基本操作
来源:互联网 发布:荷芳抢票软件 编辑:程序博客网 时间:2024/04/30 05:45
双向链表也叫双链表,它的每个数据节点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任何一个节点开始,都可以很方便的访问它的前驱结点和后继节点。别人常常来构造双向循环链表,今天我们特立独行一下,先来尝试构造不带头结点双向非循环链表。示例代码上传至 https://github.com/chenyufeng1991/DoubleLinkedList 。
(1)定义不带头结点的双向非循环链表的节点类型
typedef struct NodeList{ int element; struct NodeList *prior; struct NodeList *next;}Node;
(2)初始化双链表
//1.初始化不带头结点的非循环双向链表void initList(Node *pNode){ pNode = NULL; printf("%s函数执行,链表初始化完成\n",__FUNCTION__);}
(3)尾插法构造双向非循环链表:
//创建非循环双向链表Node *createList(Node *pNode){ Node *pInsert; Node *pMove; pInsert = (Node*)malloc(sizeof(Node)); memset(pInsert, 0, sizeof(Node)); pInsert->next = NULL; pInsert->prior = NULL; scanf("%d",&(pInsert->element)); pMove = pNode; if (pInsert->element <= 0) { printf("%s函数执行,输入数据非法,建立链表停止\n",__FUNCTION__); return NULL; } while (pInsert->element > 0) { if (pNode == NULL) { pNode = pInsert; pMove = pNode; }else{ pMove->next = pInsert; pInsert->prior = pMove; pMove = pMove->next; } pInsert = (Node *)malloc(sizeof(Node)); memset(pInsert, 0, sizeof(Node)); pInsert->next = NULL; pInsert->prior = NULL; scanf("%d",&(pInsert->element)); } printf("%s函数执行,建立链表成功\n",__FUNCTION__); return pNode;}
(4)打印非循环双向链表
//3.打印非循环双向链表void printList(Node *pNode){ if (pNode == NULL) { printf("%s函数执行,链表为空,打印失败\n",__FUNCTION__); }else{ while (pNode != NULL) { printf("%d ",pNode->element); pNode = pNode->next; } printf("\n"); }}
(5)清空链表
//4.清除线性表L中的所有元素,使之成为一个空表Node *clearList(Node *pNode){ if (pNode == NULL) { printf("%s函数执行,原链表就是空链表,无须执行该方法\n",__FUNCTION__); return NULL; }else{ while (pNode->next != NULL) { //一次删除每一个节点 pNode = pNode->next; free(pNode->prior); pNode->prior = NULL; } //清除最后一个节点 free(pNode); pNode = NULL; printf("%s函数执行,双向非循环链表清空成功\n",__FUNCTION__); return pNode; }}
(6)计算链表长度
//5.返回不带头节点的双向链表的长度int sizeList(Node *pNode){ int i = 0; if (pNode == NULL) { printf("%s函数执行,链表为空,长度为0\n",__FUNCTION__); return 0; }else{ while (pNode != NULL) { i++; pNode = pNode->next; } printf("%s函数执行,链表长度为%d\n",__FUNCTION__,i); return i; }}
(7)判断链表是否为空
//6.检查双链表链表是否为空,若为空则返回1,否则返回0int isEmptyList(Node *pNode){ if (pNode == NULL) { printf("%s函数执行,当前链表为空\n",__FUNCTION__); return 1; } printf("%s函数执行,当前链表非空\n",__FUNCTION__); return 0;}
(8)查找双链表某个位置的元素
//7.返回不带头节点的双向非循环链表中第pos位置的元素int getElement(Node *pNode,int pos){ int i = 1; Node *pMove; pMove = pNode; while (pMove != NULL) { if (i == pos) { printf("%s函数执行,第pos=%d位置的元素是%d\n",__FUNCTION__,pos,pMove->element); return pMove->element; } i++; pMove = pMove->next; } printf("%s函数执行,获取pos位置的元素失败\n",__FUNCTION__); return -1;}
(9)返回某元素在链表中的内存地址
//8.从不带头结点的双链表中查找具有给定值x的第一个元素,若查找成功则返回该结点data域的存储地址,否则返回NULLint *getElemAddr(Node *pNode,int x){ Node *pMove; pMove = pNode; while (pMove != NULL) { if (pMove->element == x) { printf("%s函数执行,x=%d元素的内存地址为:0x%x\n",__FUNCTION__,x,&(pMove->element)); return &(pMove->element); } pMove = pMove->next; } printf("%s函数执行,获取x=%d内存地址失败\n",__FUNCTION__,x); return &(pMove->element);}
(10)修改某个节点的值
//9.把双链表中第pos个结点的值修改为x的值,若修改成功返回1,否则返回0int modifyElem(Node *pNode,int pos,int x){ int i = 1; Node *pMove; pMove = pNode; while (pMove != NULL) { if (i == pos) { pMove->element = x; printf("%s函数执行,修改pos=%d位置的元素成功\n",__FUNCTION__,pos); return 1; } i++; pMove = pMove->next; } printf("%s函数执行,修改pos=%d位置的元素失败\n",__FUNCTION__,pos); return 1;}
(11)表头插入一个节点
//10.向不带头结点的非循环双向链表头部插入一个节点Node *insertHeadList(Node *pNode,int x){ Node *pInsert; pInsert = (Node*)malloc(sizeof(Node)); memset(pInsert, 0, sizeof(Node)); pInsert->next = NULL; pInsert->prior = NULL; pInsert->element = x; //这里要考虑原链表为空的情况 if (pNode == NULL) { pNode = pInsert; printf("%s函数执行,在头部插入节点成功\n",__FUNCTION__); return pNode; } pInsert->next = pNode; pNode->prior = pInsert; pNode = pInsert; printf("%s函数执行,在头部插入节点成功\n",__FUNCTION__); return pNode;}
//11.向不带头结点的非循环双向链表尾部插入一个节点Node *insertTailList(Node *pNode,int x){ Node *pMove; Node *pInsert; pInsert = (Node*)malloc(sizeof(Node)); memset(pInsert, 0, sizeof(Node)); pInsert->next = NULL; pInsert->prior = NULL; pInsert->element = x; pMove = pNode; //这里要考虑原链表为空的情况 if (pNode == NULL) { pNode = pInsert; printf("%s函数执行,在尾部插入节点成功\n",__FUNCTION__); return pNode; } while (pMove->next != NULL) { pMove = pMove->next; } pMove->next = pInsert; pInsert->prior = pMove; printf("%s函数执行,在尾部插入节点成功\n",__FUNCTION__); return pNode;}
(13)测试函数
int main(int argc, const char * argv[]) { Node *pList; initList(pList); printList(pList); sizeList(pList); pList = createList(pList); printList(pList); sizeList(pList); isEmptyList(pList); getElement(pList, 4); getElemAddr(pList, 5); modifyElem(pList, 4, 1111); printList(pList); pList = insertHeadList(pList, 8888); printList(pList); pList = insertTailList(pList,9999); printList(pList); pList = clearList(pList); printList(pList); return 0;}
2 0
- C语言实现双向非循环链表(不带头结点)的基本操作
- C语言实现双向非循环链表(带头结点尾结点)的基本操作
- C语言实现双向非循环链表(不带头结点)的逆序打印
- C语言实现双向非循环链表(不带头结点)的节点插入
- C语言实现双向非循环链表(不带头结点)的清空
- C语言实现双向非循环链表(带头结点尾结点)的节点插入
- C实现头插法和尾插法来构建双向非循环链表(带头结点尾结点)
- C语言实现非循环双链表节点的删除(不带头结点)
- 不带头节点的双向循环链表基本操作
- C语言实现单链表(带头结点)的基本操作
- C语言实现单链表(不带头结点)的基本操作
- 经典算法学习——非循环双向链表实现冒泡排序(不带头结点)
- C语言实现非循环双链表节点的删除(带头结点尾结点)
- C语言实现单链表(带头结点)的基本操作(创建,头插法,尾插法,删除结点,打印链表)
- C语言实现单链表(带头结点)的基本操作(创建,头插法,尾插法,删除结点,打印链表)
- 带头结点的双向循环链表
- 带头结点的双向循环链表
- 带头结点的双向循环链表
- 【2016半年总】——从懵懂到清晰,经历时间的蜕变
- Activity堆栈详解
- 模板_LinkCutTree
- mysql Slave_IO_Running:NO(解决方法)
- 算法代码实现之冒泡排序,Golang(Go语言)实现
- C语言实现双向非循环链表(不带头结点)的基本操作
- 微信零钱提现不到账
- Android通过DexClassLoader加载apk文件
- POJ3252数位DP
- LeetCode题解:Maximum Depth of Binary Tree
- 《JAVA编程思想》日志(三)------操作符
- Java 快速排序
- mybatis学习笔记(1)-对原生jdbc程序中的问题总结
- H5 canvas drawImage 无法显示