线性表的链式基本操作和实现

it2025-03-28  7


文章目录

前言1.单链表的基本操作2.其他操作3.主函数 总结

前言

和顺序表相比,链式存储结构在实现插入,删除的操作时,不需要移动大量的数据元素。所以链表适用于经常需要进行插入和删除操作的线性表。


1.单链表的基本操作

代码如下(示例):

//初始化线性表 void InitList(LinkList& L) { L = (LinkList)malloc(sizeof(LNode));//malloc函数申请内存 if (!L) exit(OVERFLOW); L->next = NULL; } //销毁线性表 void DestoryList(LinkList& L) { LinkList q; while (L) { q = L->next; free(L);//释放头结点的内存 L = q; } } //清空线性表 void ClearList(LinkList L) { LinkList p = L->next; L->next = NULL; DestoryList(p); } //判断线性表是否为空 Status ListEmpty(LinkList L) { if (L->next) return TRUE; else return FALSE; } //返回线性表的元素个数 int ListLength(LinkList L) { int i=0; LinkList p = L->next; while (p) { p = p->next; i++; } return i; } //用e返回线性表的第i个元素 Status GetData(LinkList L, int i, ElemType& e) { LinkList p = L->next; while (--i && p) p = p->next;//找出第i-1个元素 if (i < 0 || !p) return ERROR; e = p->data; return OK; } //找出第一个与e满足compare关系的元素的位置 int LocateData(LinkList L, ElemType& e, Status(*compare)(ElemType, ElemType)) { int i = 0; LinkList p = L->next; while (p) { i++; if (compare(p->data, e)) return i; p = p->next; } return 0; } //cur_e:当前元素;pre_e:所找前驱 Status PriorData(LinkList L, ElemType cur_e, ElemType& pre_e) { LinkList q,p = L->next; while (p && p->next) { q = p->next; if (q->data == cur_e) { pre_e = p->data; } p = q;//即p=p->next } return ERROR; } //用next_e返回后继 Status NextData(LinkList L, ElemType cur_e, ElemType& next_e) { LinkList p = L->next; while (p && p->next) { if (p->data == cur_e) { next_e = p->next->data; return OK; } p = p->next; } return ERROR; } //在链表的第i个位置之前插入新元素e Status ListInsert(LinkList L, int i, ElemType e) { int j = 0; LinkList s,p = L; while (p && j<i-1)//找出第i-1个元素 { j++; p = p->next; } if (!p || j > j - 1) return ERROR; s = (LinkList)malloc(sizeof(LNode));//新建一个节点用来插入新元素 s->data = e; s->next = p->next; p->next = s; } //删除第i个元素,并用e保存被删除的元素值 Status ListDelete(LinkList L, int i, ElemType e) { int j = 0; LinkList p = L,q; while (p->next && j<i-1) { j++; p = p->next; } if (!p->next || j > i - 1) return ERROR; q = p->next; e = q->data; free(q);//释放被删除元素的节点 return OK; } //遍历函数 void ListTraverse(LinkList L, void(*visit)(ElemType)) { LinkList p = L->next; while (p) { visit(p->data); p = p->next; } printf("\n"); }

2.其他操作

代码如下(示例):

//头插法 void CreateBack(LinkList& L, int n) { int i; LinkList p; L = (LinkList)malloc(sizeof(LNode));//初始化L L->next = NULL; printf("请输入%d个数字:\n", n); for (i = n; i > 0; --i) { p = (LinkList)malloc(sizeof(LNode)); scanf("%d", &p->data); p->next = L->next; L->next = p;//将p插入到头结点之后 } } //尾插法 void CreateAdvance(LinkList& L, int n) { int i; LinkList p,q; L = (LinkList)malloc(sizeof(ElemType)); L->next = NULL; q = L; printf("请输入%d个数字:",n); for (i = 0; i < n; i++) { p = (LinkList)malloc(sizeof(ElemType)); scanf("%d", &p->data); q->next = p; q = p;//即q=q->next } p->next = NULL;//将最后一个节点的next设为NULL } //合并两个非递减链表 void MergeList(LinkList La, LinkList Lb, LinkList& Lc) { LinkList pa, pb ,pc; pa = La->next; pb = Lb->next; pc = Lc = La; while (pa && pb) { if (pa->data <= pb->data) { pc->next = pa; pc = pc->next; pa = pa->next; } else { pc->next = pb; pc = pc->next; pb = pb->next; } pc->next = pa ? pa : pb;//将非空的部分插入到Lc之后 free(Lb);//释放Lb的头结点 Lb = NULL; } } //逆置线性表(头插法) void ReverseList(LinkList& L) { LinkList p, q ,head; head = L; p = head->next; head->next = NULL;//设置head->next为空的目的是当输出链表元素时有终止条件 while (p) { q = p; p = p->next; q->next = head->next; head->next = q; } }

##Menu-Choice函数

void Menu(void) { printf("----------------------------------\n"); printf("1.--------初始化链表---------------\n"); printf("2.--------销毁链表-----------------\n"); printf("3.--------清空链表-----------------\n"); printf("4.--------链表长度-----------------\n"); printf("5.--------指定位置的元素值----------\n"); printf("6.--------链表已存在元素的位置------\n"); printf("7.--------求输入元素的直接前驱------\n"); printf("8.--------求输入元素的直接后继------\n"); printf("9.--------在选中的位置插入一个元素---\n"); printf("10.-------删除选中位置的元素--------\n"); printf("11.-------输出此时的链表元素--------\n"); printf("12.-------初始化链表并用头插法实现---\n"); printf("13.-------初始化链表并用尾插法实现---\n"); printf("14.-------实现单链表的逆序存放------\n"); printf("----------输入一个负数结束----------\n"); printf("\n"); } void MenuChoice(LinkList &L) { int choice,i = 0; ElemType e = 0,cur; printf("请选择你要做出的操作:"); scanf("%d", &choice); if (choice < 0) exit(ERROR); switch (choice) { case 1: InitList(L); if (L) printf("初始化成功!\n"); break; case 2: DestoryList(L); if (!L) printf("销毁成功!\n"); break; case 3: ClearList(L); if (!L->next) printf("链表已清空!\n"); break; case 4: int length; length = ListLength(L); printf("链表的长度为%d", length); break; case 5: int data,i; ElemType e; printf("输入你想获取那个位置的值:"); scanf("%d", &i); data = GetData(L, i, e); printf("第%d个位置的值为%d\n", i, e); break; case 6: printf("输入你想获取那个元素的位置:"); scanf("%d", &e); if(LocateData(L, e, Compare)) printf("%d在线性表的第%d个位置上\n", e, i); break; case 7: ElemType cur; printf("输入你想获得那个元素的直接前驱:"); scanf("%d", &cur); if(PriorData(L, cur, e)) printf("%d的直接前驱为%d\n", cur, e); break; case 8: printf("输入你想获得那个元素的直接后继:"); scanf("%d", &cur); if(NextData(L, cur, e)) printf("%d的直接后继为%d\n", cur, e); break; case 9: printf("输入你想在那个元素之前插入元素:"); scanf("%d", &i); printf("输入你想在这个位置插入那个元素:"); scanf("%d", &e); if (ListInsert(L, i, e)) { printf("插入成功!此时线性表为:"); ListTraverse(L, Print); } break; case 10: printf("输入你想删除元素的位置:"); scanf("%d", &i); if (ListDelete(L, i, e)) { printf("删除成功!此时线性表为:"); ListTraverse(L, Print); } break; case 11: printf("此时线性表的元素为:"); ListTraverse(L, Print); break; case 12: int n; printf("请输入线性表的长度:"); scanf("%d", &n); CreateBack(L, n); printf("此时线性表的元素为:"); ListTraverse(L, Print); case 13: printf("请输入线性表的长度:"); scanf("%d", &n); CreateAdvance(L, n); printf("此时线性表的元素为:"); ListTraverse(L, Print); break; case 14: ReverseList(L); printf("此线性表元素逆序后为:"); ListTraverse(L, Print); break; default: printf("请输入正确的选择!!!"); break; } }

3.主函数

代码如下(示例):

int main() { LinkList L; while (1) { Menu(); MenuChoice(L); } return 0; }

总结

提示:链表的基本操作可以帮我们处理含有大量数据的增删

最新回复(0)