LinkList 单链表的实现
2016-07-27 18:01
239 查看
LinkList.h
例
存在两个单链表A和B,其中的元素都是非递减排列,编写算法归并单链表A和B,得到单链表C,C的元素值按照非递减排列。要求表C利用原来表A和B的结点空间,不申请额外空间
以上内容来自《跟我学数据结构》陈锐 葛丽萍编著,尊重作者,购买图书。
#include "stdio.h" #include "math.h" #include "malloc.h" #include "stdlib.h" //typedef int DataType; //LinkNode是链表的结点类型,LinkList是指向链表的指针类型 //如果定义了 LinkList L;则定义了一个链表,L指向该链表的第一个结点 //不带头结点,链表为空,L=NULL;带头结点,链表为空,L->next = NULL; typedef struct Node{ DataType data; struct Node *next; }LinkNode, *LinkList; //初始化单链表,将单链表置空 //将单链表初始化为空。动态生成一个头结点,并将头结点的指针域置空 //根据typedef定义,LinkList 就是 ListNode* ,即 ListNode 的指针; //根据InitList函数的形参声明,head 变量是 LinkList 类型的指针,即 ListNode 的二级指针。 //因此,*head 才是LinkList类型。 void InitList(LinkList *head) { if ((*head = (LinkList)malloc(sizeof(LinkNode))) == NULL) /*为头结点分配一个存储空间*/ exit(-1); /* exit是一个进程,-1表示异常退出,要包含头文件 "stdlib.h" */ (*head)->next = NULL; } //判断单链表是否为空,就是通过判断头结点的 指针域是否为空 //空返回 1 ; 否则返回 0; int ListEmpty(LinkList head) { if (head->next == NULL) return 1; else return 0; } //按序号查找操作 //查找单链表中第i个结点。查找成功返回该结点的指针,否则返回NULL标志失败 LinkNode* Get(LinkList head, int i) { LinkNode *p; int j; if (ListEmpty(head)) //不为 0 表示链表为空 return NULL; if (i < 1) //判断序号是否合法 return NULL; j = 0; p = head; while (p->next != NULL && j < i) { p = p->next; j++; } if (j == i) return p; //找到第 i 个结点,返回指针p; else return NULL; //如果没找到第 i 个元素,返回NULL; } //按内容查找操作 //查找线性表中元素值为 e 的元素 // db90 成功返回对应元素的结点的指针;否则返回NULL,表示失败 LinkNode* LocateElem(LinkList head, DataType e) { LinkNode* p; p = head->next; //指针p指向第一个结点 while (p) { if (p->data != e) p = p->next; else break; } return p; } //定位操作 //按内容查找并返回该结点的序号,称为定位函数 //查找线性表中元素值为 e 的元素,成功返回对应元素的序号,否则返回0; int LocatePos(LinkList head, DataType e) { LinkNode* p; int i; if (ListEmpty(head)) //先判断链表是否为空 return 0; p = head->next; //指针p指向第一个结点 i = 1; while (p) { if (p->data == e) return i; else { p = p->next; i++; } } if (!p) //while 循环完也没有找到e,说明不存在e,返回0; return 0; } //插入操作 //在单链表中第i个位置插入一个结点,结点的元素值为e,插入成功返回1,失败返回0 int InsertList(LinkList head, int i, DataType e) { LinkNode *p, *pre; //指针pre 是指向第i个元素的前驱结点,指针p指向新生成的结点 int j; pre = head; j = 0; while (pre->next != NULL&&j < i - 1) //为了找到第i-1个结点 { pre = pre->next; j++; } if (j != i - 1) //现在j应该等于 i-1,不等于说明没找到,插入位置错误 { printf("插入位置错误"); return 0; } if ((p = (LinkNode*)malloc(sizeof(LinkNode))) == NULL) exit(-1); //进程异常退出申请新结点失败 p->data = e; //插入结点操作,顺序不能调换 p->next = pre->next; pre->next = p; return 1; } //删除操作 //删除单链表中的第i个位置的结点。删除成功返回1,失败返回0 int DeleteList(LinkList head, int i, DataType *e) { LinkNode *p, *pre; int j; pre = head; j = 0; while (pre->next != NULL && pre->next->next != NULL && j < i - 1) /*判断是否找到前驱结点*/ { pre = pre->next; j++; } if (j != i - 1) //没有找到要删除的结点位置,说明删除位置错误 { printf("删除位置错误"); return 0; } //走到这里j=i-1 //指针p指向单链表的第i个结点,并将该结点的数据域赋值给 e p = pre->next; *e = p->data; //将前驱结点的指针域指向要删除结点的下一个结点 pre->next = p->next; //释放 p 指向的结点 free(p); return 1; } //求表长操作 //就是返回单链表元素个数 int ListLength(LinkList head) { LinkNode *p; int count = 0; p = head; while (p->next != NULL) { p = p->next; count++; } return count; } //销毁链表操作 释放结点空间 void DestoryList(LinkList head) { LinkNode *p, *q; p = head; while (p != NULL) { q = p; p = p->next; free(q); } }
例
存在两个单链表A和B,其中的元素都是非递减排列,编写算法归并单链表A和B,得到单链表C,C的元素值按照非递减排列。要求表C利用原来表A和B的结点空间,不申请额外空间
#include <stdio.h> #include <malloc.h> #include <stdlib.h> #define LISTSIZE 100 typedef int DataType; #include "LinkList.h" //将链表A和B的元素合并到C中的函数声明 void MergeList(LinkList A, LinkList B, LinkList *C); void main() { int i; DataType a[] = { 6,7,9,14,37,45,65,67 }; DataType b[] = { 3,7,11,34,45,89 }; LinkList A, B, C; LinkNode *p; InitList(&A); InitList(&B); InitList(&C); //将数组a中的元素插入到单链表A中 for (i = 1; i <= (sizeof(a) / sizeof(a[0])); i++) { if (InsertList(A, i, a[i - 1]) == 0) { printf("位置不合法"); return; } } //将数组b中的元素插入到单链表B中 for (i = 1; i <= (sizeof(b) / sizeof(b[0])); i++) { if (InsertList(B, i, b[i - 1]) == 0) { printf("位置不合法"); return; } } printf("单链表A中元素有%d个:\n", ListLength(A)); for (i = 1; i <= ListLength(A); i++) { p = Get(A, i); if (p) printf("%4d", p->data); } printf("\n"); printf("单链表B中元素有%d个:\n", ListLength(B)); for (i = 1; i <= ListLength(B); i++) { p = Get(B, i); if (p) printf("%4d", p->data); } printf("\n"); MergeList(A, B, &C); printf("将单链表A和B合并到C后,C中的元素有%d个:", ListLength(C)); for (i = 1; i <= ListLength(C); i++) { p = Get(C, i); if (p) printf("%4d", p->data); } printf("\n"); system("pause"); } /*单链表A和B中的元素非递减排列,将单链表A和B中的元素合并到C中, C中的元素仍然按照递减排列*/ void MergeList(LinkList A, LinkList B, LinkList *C) { LinkNode *pa, *pb, *pc; //指向单链表A,B,C的指针 pa = A->next; pb = B->next; *C = A; //将单链表A的头结点作为C的头结点,此时不用释放A头结点 (*C)->next = NULL; pc = *C; while (pa && pb) { if (pa->data <= pb->data) { //如果A中的元素小于或等于B中的元素,将A中的元素的结点作为C的结点 pc->next = pa; //直接将指赋值给pc,包括了数据域和指针域 pc = pa; pa = pa->next; } else { //如果A中的元素大于B中的元素,将B中的元素的结点作为C的结点 pc->next = pb; pc = pb; pb = pb->next; } } pc->next = pa ? pa : pb; //将剩余结点插入到C中 free(B); //释放B的头结点 }
以上内容来自《跟我学数据结构》陈锐 葛丽萍编著,尊重作者,购买图书。
相关文章推荐
- Java高级-线程同步lock与unlock使用
- JQuery 网页选项卡制作
- JQuery 网页选项卡制作
- wps for linux 不能正常使用中文输入法
- Android应用setContentView与LayoutInflater加载解析机制源码分析
- Java的4种单例模式
- 对程序员来说,提高薪水最好的建议是什么?
- UVALive 3635 Pie (二分)
- Swift 流程控制
- ssh第一次输入免yes 和ssh-keygen免交互
- volatile关键字
- winform版弹框操作
- ios Byte *bt 输出 输出指针对应的内容
- 《nodejs实战》一
- JQuery学习之旅(3)
- pytho序列,字符串,元组---学习笔记
- UML的9种图例解析
- 面向对象六大原则----开闭原则
- android6.0 power显示(亮度等)深入分析(一)PowerManagerService & DisplayPowerController
- Android初学之第一个Android程序:文件浏览器