线性表的顺序存储实现(二)单链表、双链表、循环链表

1|0单链表

1|1带头结点

1|2初始化

// 带头结点的单链表 bool InitList_head(LinkList &L) { L = (LNode *)malloc(sizeof(LNode)); // 分配一个头节点 if (L == NULL) { return false; // 内存不足,分配失败 } L->next = NULL; // 头结点之后还没节点 return true; }

1|3空链判断

bool Empty_head(LinkList L) { if (L->next == NULL) // 只有一个头结点的 “带头结点的单链表” => 空表 { return true; } else { return false; } }

1|4

1|0按位序插入

bool ListInsert(LinkList &L, int i, int e) // 按位序插入 { if (i < 1) { return false; } LNode *p; // 指针p指向当前扫描到的节点 int j = 0; // 当前p指向的是第几个节点 p = L; while (p != NULL && j < i - 1) // 遍历链表找到第i-1个节点 { p = p->next; j++; } if (p == NULL) // i值不合法 插到无前驱也无后继的位置 { return false; } LNode *s = (LNode *)malloc(sizeof(LNode)); // 申请一个新的节点空间 s->data = e; s->next = p->next; // s 指向第i个元素 p->next = s; // 第i-1个元素指向 s return true; }

1|0某结点前插入

bool InsertPrioNode(LNode *p, int e) // 在指定节p点前插入元素 e // 思路:先插到p之后,再交换p存的值p->data与新节点存的值e { if( p==NULL ) { return false; } LNode *s = (LNode *)malloc(sizeof( LNode )); if( s==NULL ) { return false; } s->next = p->next; // s 插入到 p 后面 p->next = s; s->data = p->data; // p s 互换data p->data = e; return true; }

1|0某结点后插入

bool InsertNextNode(LNode *p, int e) // 在指定节点p后插入元素 e { if(p == NULL) { return false; } LNode *s = (LNode *)malloc(sizeof(LNode)); if(s == NULL) // 内存分配失败 { return false; } s->data = e; s->next = p->next; // s 指向 p的下一个节点 p->next = s; // p 指向 s return true; }

1|5

1|0按位序删

bool ListDelete(LinkList &L, int i, int &e) // 按位序删除 { if( i<1 ) { return false; } LNode *p; // 指向当前扫描到的节点 int j = 0; // 当前节点位序 p = L; while( p!=NULL && j<i-1 ) // 循环到 j = i-1; { p = p->next; j++; } if( p==NULL ) // 位置 i 不合法 { return false; } if( p->next == NULL ) // 不存在第 i 位元素 { return false; } LNode *q = p->next; e = q->data; p->next = q->next; free(q); return true; }

1|0删除指定结点

bool DeleteNode(LNode *p) // 删除指定节点 // 思路:*p 与其后继 q 互换值, 删掉后继节点 q, 但 { if( p==NULL ) { return false; } LNode *q = p->next; // q 指向 *p 的后继节点 p->data = p->next->data; p->next = q->next; // 将 q 节点从链中断开 free(q); return true; }

1|6

1|0按位序查找

LNode * GetElem(LinkList &L, int i) // 按位查找 返回第i位元素 { if (i < 1) { return NULL; } LNode *p; // 指针p指向当前扫描到的节点 int j=0; // 当前p指向的是第几个节点 p = L; while (p != NULL && j < i) // 遍历链表找到第 i 个节点 { p = p->next; j++; } // if (p == NULL) // i值不合法 -> p退出时正好时 NULL // { // return NULL; // } return p; }

1|0按值查找

LNode * LocateElem( LinkList L, int e ) // 按值查找 { LNode *p = L->next; // 从第 1 个元素开始查找 while( p != NULL && p->data != e) // 循环到值为e的节点 p { p = p->next; } return p; }

1|7链表长度

int Length(LinkList L) { int len = 0; // 统计表长 LNode *p = L; while( p->next != NULL ) { p = p->next; len++; } return len; }

1|8打印链表

void PrintLink( LinkList L ) { printf("Length: %i \n", Length(L)); LNode *p; int t=0; // 记录位序 p = L->next; // 从头结点之后开始打印 printf("HeadNode ->"); while( p != NULL ) { t++; printf(" %i -> ", p->data); p = p->next; } puts(" NULL\n"); }

1|9主函数(用于测试)

int main() { // 创建单链表 LinkList L; InitList_head(L); PrintLink(L); // 按位序插入 for(int i=0; i<5; i++) { ListInsert(L, i+1, i+1); } PrintLink(L); // 在某节点后插入 LNode *np; np = L->next; InsertNextNode(np, 100); printf("insert next node successful... node->data: %i\n", np->next->data); PrintLink(L); // 在某节点前插入 LNode *pp; pp = L->next; InsertPrioNode(pp, 100); printf("insert prio node successful... node->data: %i\n", pp->next->data); PrintLink(L); // 按位序删除 int e; ListDelete(L, 3, e); printf("del NO.3 %i successful...\n", e); PrintLink(L); // 删指定节点 LNode *dp; dp = L->next; DeleteNode(dp); printf("del node successful... NOW node->data=%i \n", dp->data); PrintLink(L); // 按位序查找 LNode *p; p = GetElem(L, 3); printf("GetElem NO.3 : %i\n", p->data); // 按值查找 LNode *q; q = LocateElem(L, 4); printf("LocateElem 4 : q->data = %i\n", q->data); return 0; }

1|10测试结果

image

1|11不带头结点


__EOF__

本文作者HUGBOY
本文链接https://www.cnblogs.com/hugboy/p/16265145.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   HUGBOY  阅读(49)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2021-05-13 Linux 操作系统(四)用户组管理&进程管理&任务调度
点击右上角即可分享
微信分享提示