一、基础知识:链表(线性表的链式存储结构)
(1)特点:逻辑关系相邻,物理位置不一定相邻。
(2)分类:
a.不带头节点
b.带头节点
(3)单链表的存储结构:
typedef struct SListNode
{
DataType data;
struct SListNode* next;
}SListNode;
二、代码实现(因避开使用二级指针,所以代码中使用了c++中的引用):此处构造的为不带头节点的链表
方法一:
(1)sList.h
#pragma once
typedef int DataType;
typedef struct SListNode
{
DataType data;
struct SListNode* next;
}SListNode;
void PushBack(SListNode* & pHead, DataType d);
void PopBack(SListNode* & pHead);
void PushFront(SListNode* & pHead, DataType d);
void PopFront(SListNode* & pHead);
void PrintList(SListNode* pHead);
SListNode* Find(SListNode* & pHead, DataType d);
void Insert(SListNode* & pos, DataType d);
(2)sList.cpp
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include "sList.h"
SListNode* MakeNode(DataType d)
{
SListNode* tmp = (SListNode*)malloc(sizeof(SListNode));
tmp->data = d;
tmp->next = NULL;
return tmp;
}
void PushBack(SListNode* & pHead, DataType d)
{
//1.空
//2.不空
if(pHead == NULL)
{
pHead = MakeNode(d);
}
else
{
//先找尾,再插入新节点
SListNode* tail = pHead;
while(tail->next != NULL)
{
tail = tail->next;
}
tail->next = MakeNode(d);
}
}
void PopBack(SListNode* & pHead)
{
//1.空
//2.一个节点
//3.多个节点
if(pHead == NULL)
{
return;
}
else if (pHead->next == NULL)
{
free(pHead);
pHead = NULL;
}
else
{
SListNode* tail = pHead;
SListNode* prev = NULL;
while(tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
prev->next = NULL;
free(tail);
}
}
void PushFront(SListNode* & pHead, DataType d)
{
if(pHead == NULL)
{
pHead = MakeNode(d);
}
else
{
SListNode* tmp = pHead;
pHead = MakeNode(d);
pHead->next = tmp;
}
}
void PopFront(SListNode* & pHead)
{
if(!pHead)
{
printf("List is empty!");
return;
}
else
{
SListNode* tmp = pHead;
pHead = pHead->next;
free(tmp);
}
}
SListNode* Find(SListNode* & pHead, DataType d)
{
SListNode* find = pHead;
while(find)
{
if(find->data == d)
return find;
find = find->next;
}
return NULL;
}
void Insert(SListNode* & pos, DataType d)
{
assert(pos);
/*
方法一:
SListNode* tmp = MakeNode(d);
tmp->next = pos->next;
pos->next = tmp;
*/
//方法二:
SListNode* next = pos->next;
pos->next = MakeNode(d);
pos->next->next = next;
}
void Erase(SListNode*& pHead,SListNode* & pos)
{
assert(pos&&pHead);
SListNode* prev = pHead;
while(prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);
pos = NULL;
}
void PrintList(SListNode* pHead)
{
SListNode* tmp = pHead;
while(tmp)
{
printf("%d->", tmp->data);
tmp = tmp->next;
}
printf("NULL\n");
(3)test.cpp
#include "sList.h"
#include <stdio.h>
#include <stdlib.h>
void test1()
{
//不带头节点
SListNode* list = NULL;
PushBack(list, 1);
PushBack(list, 2);
PushBack(list, 3);
PushBack(list, 4);
// PushFront(list,0);
// PopFront(list);
// PopBack(list);
SListNode* ret = Find(list, 2);
if(ret == NULL)
{
printf("No Exist!\n");
return;
}
// Insert(ret, 4);
Erase(list,ret);
PrintList(list);
}
int main()
{
test1();
system("pause");
return 0;
方法二:
这种方法定义了两个结构体,方便以后对链表的操作,你可以在LinkList这个结构体中加入尾指针或者长度等等信息,来使操作更加简单。
typedef struct ListNode //单链表的一个结点
{
DataType data;
struct ListNode* next;
}ListNode,*pListNode;
typedef struct LinkList //链表的信息 {
pListNode pHead;
}LinkList,*pLinkList;
源文件:
1.LinkList.h
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int DataType;
typedef struct ListNode
{
DataType data;
struct ListNode* next;
}ListNode,*pListNode;
typedef struct LinkList
{
pListNode pHead;
}LinkList,*pLinkList;
void InitLinkList(pLinkList plist);
void DestoryLinkList(pLinkList plist);
void PushBack(pLinkList plist, DataType x);
void PopBack(pLinkList plist);
void PushFront(pLinkList plist, DataType x);
void PopFront(pLinkList plist);
void PrintLinkList(pLinkList plist);
pListNode Find(pLinkList plist, DataType x);
void Insert(pLinkList plist, pListNode pos, DataType x);
void Remove(pLinkList plist, DataType x);
void RemoveAll(pLinkList plist, DataType x);
void Erase(pLinkList plist, pListNode pos);
void BubbleSort(pLinkList plist);
#endif
2.LinkList.c
#include "LinkList.h"
void InitLinkList(pLinkList plist)
{
assert(plist);
plist->pHead = NULL;
}
void DestoryLinkList(pLinkList plist)
{
pListNode cur = NULL;
assert(plist);
cur = plist->pHead;
while(cur)
{
pListNode del = cur;
cur = cur->next;
free(del);
del = NULL;
}
plist->pHead = NULL;
}
pListNode BuyNode(DataType x) //创建一个结点
{
pListNode newNode = (pListNode)malloc(sizeof(ListNode));
if(NULL == newNode)
{
printf("out of memory!");
exit(0);
}
newNode->data = x;
newNode->next = NULL;
return newNode;
}
void PushBack(pLinkList plist, DataType x)
{
pListNode cur = NULL;
pListNode newNode = NULL;
assert(plist);
cur = plist->pHead;
newNode = BuyNode(x);
if(NULL == cur) //空链表
{
plist->pHead = newNode;
}
else //链表不为空
{
while(cur->next != NULL)
{
cur = cur->next;
}
cur->next = newNode;
}
}
void PopBack(pLinkList plist)
{
pListNode cur = NULL;
assert(plist);
cur = plist->pHead;
if(NULL == cur) //链表为空
{
printf("LinkList is Empty\n");
}
else if(NULL == cur->next) //链表只有一个结点
{
free(cur);
cur = NULL;
plist->pHead = NULL;
}
else //链表有两个及以上结点
{
while(cur->next->next != NULL)
{
cur = cur->next;
}
free(cur->next);
cur->next = NULL;
}
}
void PushFront(pLinkList plist, DataType x)
{
pListNode newNode = NULL;
assert(plist);
newNode = BuyNode(x);
newNode->next = plist->pHead;
plist->pHead = newNode;
}
void PopFront(pLinkList plist)
{
assert(plist);
if(NULL == plist->pHead)
{
printf("LinkList is Empty\n");
return;
}
else
{
pListNode del = plist->pHead;
plist->pHead = del->next;
free(del);
del = NULL;
}
}
void PrintLinkList(pLinkList plist)
{
pListNode cur = NULL;
assert(plist);
cur = plist->pHead;
while(cur)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
pListNode Find(pLinkList plist, DataType x)
{
pListNode cur = NULL;
assert(plist);
cur = plist->pHead;
while(cur)
{
if(cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
void Insert(pLinkList plist, pListNode pos, DataType x) //在pos之前插入
{
pListNode newNode = NULL;
assert(plist);
assert(pos);
newNode = BuyNode(x);
if(pos == plist->pHead)
{
PushFront(plist, x);
}
else
{
pListNode cur = plist->pHead;
while(cur->next != pos)
{
cur = cur->next;
}
cur->next = newNode;
newNode->next = pos;
}
}
void Remove(pLinkList plist, DataType x) //删除数据为x的结点
{
pListNode pos = NULL;
assert(plist);
pos = Find(plist, x);
if(pos == NULL)
{
printf("no find\n");
}
else if(pos == plist->pHead)
{
PopFront(plist);
}
else
{
pListNode cur = plist->pHead;
while(cur->next != pos)
{
cur = cur->next;
}
cur->next = pos->next;
free(pos);
pos = NULL;
}
}
void RemoveAll(pLinkList plist, DataType x)
{
pListNode cur = NULL;
assert(plist);
cur = plist->pHead;
if(plist->pHead == NULL)//空链表
{
return;
}
else if(plist->pHead->next == NULL) //只有一个结点
{
free(cur);
cur = NULL;
plist->pHead =NULL;
return;
}
while(cur->data == x) //头
{
pListNode del = cur;
cur = cur->next;
plist->pHead = cur;
free(del);
del = NULL;
}
while(cur && cur->next) //中间和尾
{
if(cur->next->data == x)
{
pListNode del = cur->next;
cur->next = del->next;
free(del);
del = NULL;
}
cur = cur->next;
}
}
void Erase(pLinkList plist, pListNode pos)
{
assert(pos);
assert(plist);
if(pos == plist->pHead)
{
PopFront(plist);
}
else
{
pListNode cur = plist->pHead;
while(cur->next != pos)
{
cur = cur->next;
}
cur->next = pos->next;
free(pos);
pos = NULL;
}
}
void BubbleSort(pLinkList plist)
{
int flag = 0;
pListNode cur = NULL; //控制外循环排序的趟数
pListNode log= NULL; //记录内循环上一次交换的最后一个数
pListNode cmp = NULL; //记录内循环的当前比较值
assert(plist);
log = plist->pHead;
cur = plist->pHead;
while(log)
{
log = log->next;
}
while(cur->next != NULL)
{
pListNode node = NULL;
cmp = plist->pHead;
log = node;
flag = 0;
while(cmp->next!=log)
{
if(cmp->data > cmp->next->data)
{
DataType tmp = cmp->data;
cmp->data = cmp->next->data;
cmp->next->data = tmp;
node = cmp;
flag = 1;
}
cmp = cmp->next;
}
if(flag == 0)
{
return;
}
cur = cur->next;
}
}
3.Test.c
#include "LinkList.h"
void Test1()
{
LinkList list;
InitLinkList(&list);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 4);
PushBack(&list, 5);
PrintLinkList(&list);
PopBack(&list);
PrintLinkList(&list);
PopBack(&list);
PopBack(&list);
PopBack(&list);
PopBack(&list);
PopBack(&list);
PrintLinkList(&list);
DestoryLinkList(&list);
}
void Test2()
{
LinkList list;
InitLinkList(&list);
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 3);
PushFront(&list, 4);
PushFront(&list, 5);
PrintLinkList(&list);
PopFront(&list);
PrintLinkList(&list);
PopFront(&list);
PrintLinkList(&list);
PopFront(&list);
PrintLinkList(&list);
PopFront(&list);
PrintLinkList(&list);
PopFront(&list);
PrintLinkList(&list);
PopFront(&list);
PrintLinkList(&list);
DestoryLinkList(&list);
}
void Test3()
{
LinkList list;
InitLinkList(&list);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 4);
PushBack(&list, 5);
PrintLinkList(&list);
// Insert(&list, Find(&list, 4), 3);
Insert(&list, Find(&list, 1), 3);
Insert(&list, Find(&list, 5), 3);
PrintLinkList(&list);
DestoryLinkList(&list);
}
void Test4()
{
LinkList list;
InitLinkList(&list);
PushBack(&list, 4);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 4);
PushBack(&list, 5);
PushBack(&list, 4);
PrintLinkList(&list);
// Remove(&list, 1);
// Remove(&list, 5);
// Remove(&list, 3);
RemoveAll(&list, 4);
PrintLinkList(&list);
DestoryLinkList(&list);
}
void Test5()
{
LinkList list;
InitLinkList(&list);
PushBack(&list, 4);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 4);
PushBack(&list, 5);
PushBack(&list, 4);
PrintLinkList(&list);
Erase(&list,Find(&list,3));
PrintLinkList(&list);
BubbleSort(&list);
PrintLinkList(&list);
DestoryLinkList(&list);
}
int main()
{
// Test1();
// Test2();
// Test3();
// Test4();
Test5();
system("pause");
return 0;
}