单向链表的简单实现
2016-07-22 16:41
330 查看
链表有单项链表和双向链表,在这里只讲单项链表的一些功能实现,包括链表的初始化,尾插、尾删,头插、头删,指定结点位置插入元素,删除一个x元素和所有x元素,以及删除指定位置的结点,冒泡排序等
首先定义出链表的结构,包括结点的定义和函数的声明
LinkList.h
@初始化:
只需将函数的头指针置为空
@尾插:
首先得创建一个新结点,然后找到最后一个结点,将最后一个节点的next指针指向新结点
@尾删:
1.链表为空时不操作;2.链表不为空的情况下找到最后一个结点,将其free掉并将前一个结点的next指针置为空
@头插:
1.链表如果为空,将pHead指向新创建的结点;2.如果不为空,将pHead指向新创建的结点并将新结点的next指针指向原链表的第一个结点。如图:
[b]
[/b]
[b]@头删:[/b]
[b]1.链表为空时不操作;2.链表[/b]不为空时,将pHead指向第二个结点并将第一个结点free掉
[b]
[/b]
[b]1.链表为空的情况下不操作;2.链表只有一个结点并且在该结点位置前插入;3.链表有多个结点并找到指定位置插入[/b]
[b]
[/b]
[b]1.空链表的情况下不操作;2.有一个结点时:判断该节点是不是要删除的元素;3.有多个结点时:查找要删除的元素,然后删除[/b]
[b]
[/b]
[b]@删除所有指定元素x:[/b]
1.链表为空时不操作;2.有一个结点时:判断该结点是不是要删除的元素x;3.有多个结点时:首先判断第一个结点是不是要删除的元素x,如果是,删除并继续向后寻找,直到遍历完整个链表;如果不是,就从第二个结点开始遍历
1.空链表时不操作;2.有一个结点时:判断该节点是不是要删除的结点pos;3.有多个结点时:判断第一个结点是不是要删除的结点,如果是,就将第一个结点删除并直接返回;如果不是,应继续遍历此链表知道找到要删除的结点
1.链表为空或者链表只有一个结点时:不需要排序;
2.排序时应定义一个尾指针来控制循环的次数
LinkList.c
test.c
首先定义出链表的结构,包括结点的定义和函数的声明
LinkList.h
#ifndef _LINKLIST_H__ #define _LINKLIST_H__ #include<stdio.h> #include<stdlib.h> #include<assert.h> typedef int DataType; typedef struct LinkNode //定义一个结点 { struct LinkNode *next; DataType data; }LinkNode,*pLinkNode; typedef struct LinkList //定义链表 { LinkNode *pHead; }LinkList,*pLinkList; void Init(pLinkList pList); //初始化 void Destory(pLinkList pList); //销毁 void Print(pLinkList pList); //输出 void PushBack(pLinkList pList,DataType x); //尾插 void PopBack(pLinkList pList); //尾删 void PushFront(pLinkList pList,DataType x); //头插 void PopFront(pLinkList pList); //头删 pLinkNode Find(pLinkList pList,DataType x); //公共查找函数 void Insert(pLinkList pList,pLinkNode pos,DataType x); //指定结点位置插入 void Remove(pLinkList pList,DataType x); //删除一个X元素 void RemoveAll(pLinkList pList,DataType x); //删除所有X元素 void Erase(pLinkList pList,pLinkNode pos); //删除指定位置的结点 void BubbleSort(pLinkList pList); //冒泡排序 #endif //_LINKLIST_H__接下来就是各函数的实现部分:
@初始化:
只需将函数的头指针置为空
void Init(pLinkList pList) //初始化 { assert(pList); pList->pHead = NULL; }
@尾插:
首先得创建一个新结点,然后找到最后一个结点,将最后一个节点的next指针指向新结点
void PushBack(pLinkList pList,DataType x) //尾插 { pLinkNode cur = NULL; pLinkNode newnode = NULL; assert(pList); cur = pList->pHead; newnode = BuyNode(x); //没有结点 if(NULL == pList->pHead) { pList->pHead = newnode; newnode->next = NULL; return ; } //有一个或以上的结点 while(cur->next) { cur = cur->next; } cur->next = newnode; newnode->next = NULL; }
@尾删:
1.链表为空时不操作;2.链表不为空的情况下找到最后一个结点,将其free掉并将前一个结点的next指针置为空
void PopBack(pLinkList pList) //尾删 { pLinkNode cur = NULL; pLinkNode prev = NULL; assert(pList); //没有结点 if(NULL == pList->pHead) { printf("LinList is empty!\n"); return ; } //有结点 cur = pList->pHead; while(cur->next) { prev = cur; cur = cur->next; } free(cur); cur = NULL; prev->next = NULL; }
@头插:
1.链表如果为空,将pHead指向新创建的结点;2.如果不为空,将pHead指向新创建的结点并将新结点的next指针指向原链表的第一个结点。如图:
[b]
[/b]
[b]@头删:[/b]
[b]1.链表为空时不操作;2.链表[/b]不为空时,将pHead指向第二个结点并将第一个结点free掉
[b]
[/b]
void PopFront(pLinkList pList) //头删 { pLinkNode cur = NULL; pLinkNode del = NULL; assert(pList); //无节点 if(NULL == pList->pHead) { printf("LinkList is empty!\n"); return ; } return ; //有一个或以上结点 cur = pList->pHead; del = cur; cur = cur->next; free(del); del = NULL; pList->pHead = cur; }@指定结点位置插入新元素:
[b]1.链表为空的情况下不操作;2.链表只有一个结点并且在该结点位置前插入;3.链表有多个结点并找到指定位置插入[/b]
[b]
[/b]
void Insert(pLinkList pList,pLinkNode pos,DataType x) //指定结点位置插入 { pLinkNode cur = NULL; pLinkNode prev = NULL; pLinkNode newnode = NULL; assert(pList); newnode = BuyNode(x); //无结点时 if(NULL == pList->pHead) { pList->pHead = newnode; newnode->next = NULL; return ; } //有一个结点并且在该结点前插入 if(pList->pHead == pos) { PushFront(pList,x); return ; } //有一个以上结点 cur = pList->pHead; while(cur != pos) { prev = cur; cur = cur->next; } prev->next = newnode; newnode->next = cur; }@删除一个指定元素x:
[b]1.空链表的情况下不操作;2.有一个结点时:判断该节点是不是要删除的元素;3.有多个结点时:查找要删除的元素,然后删除[/b]
[b]
[/b]
void Remove(pLinkList pList,DataType x) //删除一个X元素 { pLinkNode cur = NULL; pLinkNode prev = NULL; pLinkNode del = NULL; assert(pList); cur = pList->pHead; prev = pList->pHead; del = Find(pList,x); //无结点时 if(NULL == pList->pHead) { printf("LinkList is empty!\n"); return ; } //只有一个结点时 if(NULL == cur->next) { if(cur->data == x)//该结点元素就是要删除的元素 { free(cur); cur = NULL; pList->pHead = NULL; return ; } } //有多个结点时 else { while(cur) { if(cur->data == x) //第一个结点就是要删除的元素 { del = cur; pList->pHead = cur->next; free(del); del = NULL; return ; } prev = cur; cur = cur->next; //第二个结点开始,里边有需要删除的元素 while(cur) { if(cur->data == x) { prev->next = cur->next; free(cur); cur = NULL; return ; } prev = cur; cur = cur->next; } } } }
[b]@删除所有指定元素x:[/b]
1.链表为空时不操作;2.有一个结点时:判断该结点是不是要删除的元素x;3.有多个结点时:首先判断第一个结点是不是要删除的元素x,如果是,删除并继续向后寻找,直到遍历完整个链表;如果不是,就从第二个结点开始遍历
void RemoveAll(pLinkList pList,DataType x) //删除所有X元素 { pLinkNode prev = NULL; pLinkNode cur = NULL; assert(pList); //空链表 if(NULL == pList->pHead) { printf("LinkList is empty!\n"); return ; } cur = pList->pHead; //链表有一个结点 if(NULL == cur->next) { if(cur->data == x)//并且该结点元素就是要删除的元素 { free(cur); cur = NULL; pList->pHead = NULL; return ; } } //链表有多个结点 cur = cur->next; prev = pList->pHead; while(cur) { if(prev->data == x)//第一个结点是要删除的元素x { pList->pHead = prev->next; free(prev); prev = NULL; } if(cur->data == x)//要删除的元素存在于第一个结点之后 { prev->next = cur->next; free(cur); cur = NULL; cur = prev; } prev = cur; cur = cur->next; } }@删除指定位置的结点:
1.空链表时不操作;2.有一个结点时:判断该节点是不是要删除的结点pos;3.有多个结点时:判断第一个结点是不是要删除的结点,如果是,就将第一个结点删除并直接返回;如果不是,应继续遍历此链表知道找到要删除的结点
void Erase(pLinkList pList,pLinkNode pos) //删除指定位置的结点 { pLinkNode cur = NULL; pLinkNode prev = NULL; assert(pList); //空链表 if(NULL == pList->pHead) { printf("LinkList is empty!\n"); return ; } cur = pList->pHead; //一个节点 if(NULL == cur->next) { if(cur == pos)//判断这个结点是不是要删除的结点 { free(cur); cur = NULL; pList->pHead = NULL; } return ; } //第一个结点就是要删除的结点 if(pos == cur) { free(cur); cur = NULL; pList->pHead = NULL; } //链表有多个结点 cur = cur->next; prev = pList->pHead; while(cur) { if(cur == pos) { prev->next = cur->next; free(cur); return ; } prev = cur; cur = cur->next; } }@排序(此处用冒泡排序):
1.链表为空或者链表只有一个结点时:不需要排序;
2.排序时应定义一个尾指针来控制循环的次数
void BubbleSort(pLinkList pList) //冒泡排序 { pLinkNode tail = NULL; pLinkNode cur = NULL; assert(pList); if((pList->pHead == NULL)||(pList->pHead->next == NULL)) { printf("LinkList do not need to sort!\n"); return ; } cur = pList->pHead; while(cur != tail) { while(cur->next != tail) { if(cur->data < cur->next->data) { DataType tmp = cur->data; cur->data = cur->next->data; cur->next->data = tmp; } cur = cur->next; } tail = cur; cur = pList->pHead; } }由于在实现某些函数时要创建一个新结点或者寻找一个结点位置,因此这里可以写两个函数来实现。以下是所有函数的实现:
LinkList.c
#include"LinkList.h"
void Init(pLinkList pList) //初始化 { assert(pList); pList->pHead = NULL; }
void Destory(pLinkList pList) //销毁
{
pLinkNode cur = NULL;
pLinkNode del = NULL;
assert(pList);
cur = pList->pHead;
if(NULL == pList->pHead)//空链表
return ;
while(cur) //有一个或以上结点
{
del = cur;
cur = cur->next;
free(del);
del = NULL;
}
pList->pHead = NULL;
}
void Print(pLinkList pList) //输出
{
pLinkNode cur = NULL;
assert(pList);
cur = pList->pHead;
while(cur)
{
printf("%d->",cur->data);
cur = cur->next;
}
printf("over!\n");
}
pLinkNode BuyNode(DataType x)//创建一个新结点
{
pLinkNode NewNode = NULL;
NewNode = (pLinkNode)malloc(sizeof(LinkNode));
if(NULL == NewNode)
{
printf("out of memory!\n");
exit(EXIT_FAILURE);
}
NewNode->data = x;
return NewNode;
}
void PushBack(pLinkList pList,DataType x) //尾插 { pLinkNode cur = NULL; pLinkNode newnode = NULL; assert(pList); cur = pList->pHead; newnode = BuyNode(x); //没有结点 if(NULL == pList->pHead) { pList->pHead = newnode; newnode->next = NULL; return ; } //有一个或以上的结点 while(cur->next) { cur = cur->next; } cur->next = newnode; newnode->next = NULL; }
void PopBack(pLinkList pList) //尾删 { pLinkNode cur = NULL; pLinkNode prev = NULL; assert(pList); //没有结点 if(NULL == pList->pHead) { printf("LinList is empty!\n"); return ; } //有结点 cur = pList->pHead; while(cur->next) { prev = cur; cur = cur->next; } free(cur); cur = NULL; prev->next = NULL; }
void PushFront(pLinkList pList,DataType x) //头插
{
pLinkNode newnode = NULL;
pLinkNode cur = NULL;
assert(pList);
newnode = BuyNode(x);
//没有结点
if(NULL == pList->pHead)
{
pList->pHead = newnode;
newnode->next = NULL;
return ;
}
//有一个或以上结点
cur = pList->pHead;
pList->pHead = newnode;
newnode->next = cur;
}
void PopFront(pLinkList pList) //头删 { pLinkNode cur = NULL; pLinkNode del = NULL; assert(pList); //无节点 if(NULL == pList->pHead) { printf("LinkList is empty!\n"); return ; } return ; //有一个或以上结点 cur = pList->pHead; del = cur; cur = cur->next; free(del); del = NULL; pList->pHead = cur; }
pLinkNode Find(pLinkList pList,DataType x) //公共查找函数
{
pLinkNode cur = NULL;
assert(pList);
if(NULL == pList->pHead)
{
printf("LinkList is empty!\n");
return pList->pHead;
}
cur = pList->pHead;
while(cur)
{
if(cur->data == x)
return cur;
cur = cur->next;
}
}
void Insert(pLinkList pList,pLinkNode pos,DataType x) //指定结点位置插入 { pLinkNode cur = NULL; pLinkNode prev = NULL; pLinkNode newnode = NULL; assert(pList); newnode = BuyNode(x); //无结点时 if(NULL == pList->pHead) { pList->pHead = newnode; newnode->next = NULL; return ; } //有一个结点并且在该结点前插入 if(pList->pHead == pos) { PushFront(pList,x); return ; } //有一个以上结点 cur = pList->pHead; while(cur != pos) { prev = cur; cur = cur->next; } prev->next = newnode; newnode->next = cur; }
void Remove(pLinkList pList,DataType x) //删除一个X元素 { pLinkNode cur = NULL; pLinkNode prev = NULL; pLinkNode del = NULL; assert(pList); cur = pList->pHead; prev = pList->pHead; del = Find(pList,x); //无结点时 if(NULL == pList->pHead) { printf("LinkList is empty!\n"); return ; } //只有一个结点时 if(NULL == cur->next) { if(cur->data == x)//该结点元素就是要删除的元素 { free(cur); cur = NULL; pList->pHead = NULL; return ; } } //有多个结点时 else { while(cur) { if(cur->data == x) //第一个结点就是要删除的元素 { del = cur; pList->pHead = cur->next; free(del); del = NULL; return ; } prev = cur; cur = cur->next; //第二个结点开始,里边有需要删除的元素 while(cur) { if(cur->data == x) { prev->next = cur->next; free(cur); cur = NULL; return ; } prev = cur; cur = cur->next; } } } }
void RemoveAll(pLinkList pList,DataType x) //删除所有X元素 { pLinkNode prev = NULL; pLinkNode cur = NULL; assert(pList); //空链表 if(NULL == pList->pHead) { printf("LinkList is empty!\n"); return ; } cur = pList->pHead; //链表有一个结点 if(NULL == cur->next) { if(cur->data == x)//并且该结点元素就是要删除的元素 { free(cur); cur = NULL; pList->pHead = NULL; return ; } } //链表有多个结点 cur = cur->next; prev = pList->pHead; while(cur) { if(prev->data == x)//第一个结点是要删除的元素x { pList->pHead = prev->next; free(prev); prev = NULL; } if(cur->data == x)//要删除的元素存在于第一个结点之后 { prev->next = cur->next; free(cur); cur = NULL; cur = prev; } prev = cur; cur = cur->next; } }
void Erase(pLinkList pList,pLinkNode pos) //删除指定位置的结点 { pLinkNode cur = NULL; pLinkNode prev = NULL; assert(pList); //空链表 if(NULL == pList->pHead) { printf("LinkList is empty!\n"); return ; } cur = pList->pHead; //一个节点 if(NULL == cur->next) { if(cur == pos)//判断这个结点是不是要删除的结点 { free(cur); cur = NULL; pList->pHead = NULL; } return ; } //第一个结点就是要删除的结点 if(pos == cur) { free(cur); cur = NULL; pList->pHead = NULL; } //链表有多个结点 cur = cur->next; prev = pList->pHead; while(cur) { if(cur == pos) { prev->next = cur->next; free(cur); return ; } prev = cur; cur = cur->next; } }
void BubbleSort(pLinkList pList) //冒泡排序 { pLinkNode tail = NULL; pLinkNode cur = NULL; assert(pList); if((pList->pHead == NULL)||(pList->pHead->next == NULL)) { printf("LinkList do not need to sort!\n"); return ; } cur = pList->pHead; while(cur != tail) { while(cur->next != tail) { if(cur->data < cur->next->data) { DataType tmp = cur->data; cur->data = cur->next->data; cur->next->data = tmp; } cur = cur->next; } tail = cur; cur = pList->pHead; } }
test.c
#define _CRT_SECURE_NO_WARNINGS #include"LinkList.h" void menu() { printf("***********************************\n"); printf("******** 0.结束 1.输出 *********\n"); printf("******** 2.尾插 3.尾删 *********\n"); printf("******** 4.头插 5.头删 *********\n"); printf("******** 6.删除x 7.删除所有x ****\n"); printf("******** 8.插入指定元素 ***********\n"); printf("******** 9.删除指定结点 ***********\n"); printf("******** 10.排序 ***********\n"); } int main() { LinkList mylist; int input = 1; DataType data = 0; DataType p = NULL; pLinkNode pos = NULL; Init(&mylist); while(1) { menu(); printf("请输入选项:"); scanf("%d",&input); printf("\n"); switch(input) { case 0: exit(0); break; case 1: Print(&mylist); break; case 2: printf("请输入插入的数:"); scanf("%d",&data); PushBack(&mylist,data); break; case 3: PopBack(&mylist); break; case 4: printf("请输入插入的数:"); scanf("%d",&data); PushFront(&mylist,data); break; case 5: PopFront(&mylist); break; case 6: printf("输入要删除的数:"); scanf("%d",&data); Remove(&mylist,data); break; case 7: printf("输入要删除的数:"); scanf("%d",&data); RemoveAll(&mylist,data); break; case 8: printf("请输入要在哪一个位置前插入:"); scanf("%d",&p); printf("请输入要插入的数:"); scanf("%d",&data); pos = Find(&mylist,p); Insert(&mylist,pos,data); break; case 9: printf("输入要删除某个位置的结点:"); scanf("%d",&data); pos = Find(&mylist,data); Erase(&mylist,pos); break; case 10: BubbleSort(&mylist); break; default: printf("无效选择!\n"); break; } } Destory(&mylist); system("pause"); return 0; }
相关文章推荐
- (C++版)链表(一)——实现单向链表创建、插入、删除等相关操作
- 单向链表遍历反转 Javascript实现
- 单向链表常见的笔试面试题
- git stash 使用有感
- 关于 spring3 和spring4 中返回json 以及调用 js 和对原项目的修改
- 字符串中单词的交换与单词翻转(一)
- centos安装node mongodb supervisor
- HDU 5324 (CDQ分治 树状数组)
- 以写代学:python 数据类型之数字,位运算符
- php的clone 浅拷贝
- 【算法】各种哈希算法
- GDataXMLNode使用
- C++对象内存分配
- JAVA学习笔记--基本事件
- 七步从AngularJS菜鸟到专家(4和5):指令和表达式
- 如何在Android Studio中创建assets文件夹
- 鞍点-week7-C语言习题集
- input file文件上传
- 检测AppStore软件更新
- SPL - Microsoft® Windows Spool File Format