链表ADT实现
2016-08-16 22:29
169 查看
链表的定义:
链表链表有一系列不必再内存中连续的结构组成,不需要使用地址连续的存储单元。它是通过“链”来建立逻辑关系的,因此在对链表进行插入,删除操作时不需要移动元素,而只需要修改指针即可。链表分类:按是否包含指向前继的指针可分为单链表和双向链表;按是否成环状可以分为循环链表和非循环链表。
由于连表示离散的分布在存储空间的,因此链表是非随机存取的,只能从某个特定节点开始遍历一次查找。
通常为方便操作,在链表第一个节点前附加一个头节点,头节点的指针与指向链表的第一个元素节点。
链表的实现与常见算法
单链表
每个结构含有表元素和指向包含该元素后继的结构的指针。除了头节点,每一个结点都有唯一的前继。除最后一个结点,每一个结点都有一个后继。
插入:
删除:
双向链表
双向链表与单链表的不同之处在于,双向链表的每个结点含有两个指针域,其中一个指向直接前继,一个指向直接后继。这样双向链表可以沿两个方向进行遍历;插入:
删除:
struct LNode { ElementType e; PtrToLNode Next; };
typedef struct LNode *PtrToLNode;
typedef PtrToLNode List;
List List_Init(void) { List L = (List)malloc(sizeof(LNode)); L->Next = NULL; return L; } int List_IsEmpty(List L) { if (L->Next = NULL) return 1; else return 0; } void List_Print(List L) { PtrToLNode p = L->Next; while (p){ printf("%d\t", p->e); p = p->Next; } printf("\n"); } void List_Pre_Create(List L)//头插法建立单链表 { ElementType x; scanf("%d", &x); while (x != 9999) { PtrToLNode p = (PtrToLNode)malloc(sizeof(LNode)); p->e = x; p->Next = L->Next; L->Next = p; scanf("%d", &x); } } void List_Post_Create(List L)//尾差法建立单链表 { ElementType x; PtrToLNode p, r = L; scanf("%d", &x); while (x != 9999) { p = (PtrToLNode)malloc(sizeof(LNode)); p->e = x; r->Next = p; r = p; scanf("%d", &x); } r->Next = NULL; } PtrToLNode List_FindPre(List L, PtrToLNode r)//返回结点r的直接前继 { PtrToLNode pre = L, p = pre->Next; while (p != r) { pre = p; p = p->Next; } return pre; } int List_Length(List L)//求链表长度 { int Length = 0; PtrToLNode p = L->Next; while (p) { ++Length; p = p->Next; } return Length; } void List_Insert(List L, Position p, ElementType x)//在结点p处插入新节点 { PtrToLNode pre = List_FindPre(L, p), s; s = (PtrToLNode)malloc(sizeof(LNode)); s->e = x; s->Next = p; pre->Next = s; } PtrToLNode List_FindMid(List L)//返回中间元素结点 { PtrToLNode p, r; p = r = L->Next; while (r->Next != NULL && r->Next->Next != NULL){ p = p->Next; r = r->Next->Next; } printf("%d\n", p->e); return p; } void List_Delete(List L, ElementType x)//删除节点 { PtrToLNode pre = L, p = L->Next, temp; while (p){ if (p->e != x) { pre = p; p = p->Next; } else{ temp = p->Next; pre->Next = temp; free(p); p = temp; } } } void List_DeleteRepeat(List L)//删除有序链表中重复元素的结点 { PtrToLNode pre = L->Next, p = pre->Next, temp; while (p){ if (pre->e == p->e) { temp = p->Next; pre->Next = temp; free(p); p = temp; } else { pre = p; p = p->Next; } } } PtrToLNode List_Last_K(List L, int k)//返回倒数第K个结点 { PtrToLNode p, r; p = r = L; if (k > List_Length(L)) { printf("The k is Bigger Than L's Length!\n"); return NULL; } for (int i = 0; i < k; ++i) r = r->Next; while (r){ r = r->Next; p = p->Next; } printf("%d\n", p->e); return p; } /*若两单链表有公共结点,则从起始公共结点至尾结点两者均相同,因此将两链表尾部对齐,开始比较第一个相同结点即为起始公共结点*/ PtrToLNode List_CommonNode(List L1, List L2)//返回两单链表的公共起始节点 { int Length1, Length2, dist; PtrToLNode longlist, shortlist; Length1 = List_Length(L1); Length2 = List_Length(L2); if (Length1 > Length2) { longlist = L1->Next; shortlist = L2->Next; dist = Length1 - Length2; } else { longlist = L2->Next; shortlist = L1->Next; dist = Length2 - Length1; } while (dist--) longlist = longlist->Next; while(longlist && longlist->e != shortlist->e){ longlist = longlist->Next; shortlist = shortlist->Next; } PtrToLNode p = longlist; while (p) { printf("%d\n", p->e); p = p->Next; } return longlist; } void List_Reverse(List L)// { PtrToLNode pre, p, r; pre = L; p = pre->Next; r = p->Next; p->Next = NULL;//将逆置后的p将成为尾结点,将其指针域置空 while (r) { pre = p; p = r; r = r->Next;//遍历链表 p->Next = pre;//逆置 } L->Next = p;//p结点将成为你逆置后的第一个节点,将头节点指向该节点 }
</pre><pre name="code" class="cpp"><pre name="code" class="cpp">void List_Reverse1(List L)//利用头插法逆置链表 { PtrToLNode p, r; p = L->Next; L->Next = NULL; while (p) { r = p->Next; p->Next = L->Next; L->Next = p; p = r; } }
List List_Reverse1(List L, int m, int n)//逆置第m个结点至第n个结点结点 { List prefirst, first, p, r; prefirst = L; first = p = L->Next; for (int i = 1; i != m; ++i) { prefirst = p; p = p->Next; }//prefirst指向第m-1个结点 first = p;//first指向第m个结点 for (int i = m; i <= n; ++i) { r = p->Next; p->Next = prefirst->Next; prefirst->Next = p; p = r; }//利用头插法将m至n结点逆置 first->Next = p;//将first的指针域指向第n+1个结点 return L; }
双链表
阅读更多
相关文章推荐
- 链表实现stack和queue,java实现(ADT思想)
- 链表ADT的实现
- 栈ADT的链表实现
- ADT堆栈的链表实现
- 用无序链表实现字典ADT(C++描述)
- C语言实现双向链表之ADT定义
- 用无序链表实现字典ADT(C++描述)
- Data Structure 初学链表(ADT实现)
- 多项式ADT的链表实现
- C_线性表(ADT)-单向循环链表的表示和实现
- 链表实践—多项式ADT(数组实现)
- 链表ADT实现(C语言)2018.3.11
- python数据结构学习笔记-2016-10-28-03-用链表实现多项式ADT
- 单链表ADT实现集合交并补
- 用无序链表实现字典ADT(C++描述)
- C语言实现单链表之ADT定义
- C 数据结构使用数组和链表实现栈
- C语言链表实现图书管理系统
- 数据结构之双向带头节点带环链表的实现
- <有道笔试题>链表加法的递归实现