赞
踩
单链表有一个一个的数据节点构成,每个节点包含数据域和指针域,数据域储存的是节点本身所需要的储存的数据信息,指针域储存的是后继节点的指针。
typedef int ElemType;
typedef struct ListNode
{
struct ListNode* next;//指向下一个节点的指针
ElemType data;//数据域
}ListNode;
//定义一个头结点存储链表的头结点地址和链表的长度,代表链表的开始,便于后面对于链表进行操作
typedef struct
{
struct ListNode* head;
int cursize;
}LinkList;
链表的存取必须从头结点开始,头指针代表链表的第一个节点,同时,由于最后一个数据元素没有直接后继,则单链表的最后一个节点的指针域为“空”(NULL)。
void Init_List(LinkList* p)
{
assert(p != nullptr);
p.head = (ListNode*)malloc(sizeof(LinkList));
if (p.head == nullptr) exit(1);
p.head = nullptr;
p.cursize = 0;
}
//购买节点函数
ListNode* BuyNode()
{
ListNode* ip = (ListNode*)malloc(sizeof(ListNode));
if (ip == nullptr)exit(1);
memset(ip, 0, sizeof(ListNode));
return ip;
}
//输出链表函数
void Print_list(LinkList& mylist)
{
ListNode* p = mylist.head->next;
while (p != nullptr)
{
printf("%d", p->data);
p = p->next;
}
}
//在主函数中但一个单链表对象,并对该对象进行初始化
int main()
{
LinkList myList;
Init_List(&myList);
return 0;
}
按数据查找:
//在链表中查询val
ListNode* FindValue(LinkList* plist, int val)
{
assert(plist != nullptr);
ListNode* p = plist->head->next;//声明一个P指针指向链表PList的第一个节点
while (p->next->next != nullptr)//如果当前节点的不是尾结点就进行循环
{
if (p->data == val)
{
return p;
}
p = p->next;
}
return nullptr;
}
按位置查找:
//按位置查找节点,查找链表中的第 POS 个节点
ListNode* FindPos(LinkList* plist, int pos)
{
assert(plist != nullptr);
if (pos<1 || pos>plist->cursize) return nullptr;//假如位置不在链表当中就不用了进行查询,直接退出
ListNode* p = plist->head->next;
while (pos != 1)
{
p = p->next;
pos--;
}
return p;
}
//查找第POS个节点的前驱
ListNode* FindPos_pre(LinkList* plist, int pos)
{
assert(plist != nullptr);
if (pos<1 || pos>plist->cursize + 1)return nullptr;
ListNode* p = plist->head;//让P指向头结点,查找模式就和上面的按位置查询一样了
while (pos != 1)
{
p = p->next;
pos--;
}
return p;
}
void Insert_Item(LinkList* plist, int pos, ElemType val)
{
assert(plist != nullptr);
ListNode* p = FindPos_pre(plist, pos);
ListNode* q = p->next;
if (nullptr == p) return;//如果插入的位置在链表之外就无法插入,直接返回
ListNode* newNode = BuyNode();//购买一个新的节点
p->next = newNode;
newNode->data = val;
newNode->next = q;
}
void Free(ListNode* pnode)
{
free(pnode);
pnode = nullptr;
}
//按位置删除,可以删除返回真,否则返回假
bool Erase_Item(LinkList* plist, int pos)
{
assert(plist != nullptr);
ListNode* pre_p = FindPos_pre(plist, pos);//找到前驱节点
if (pre_p == nullptr || pre_p->next == nullptr)
{
return false;
}//前驱为空或者要删除的位置为空都说明说明要删除位置不在链表内
ListNode* p = pre_p->next;
pre_p->next = p->next;
Free(p);//释放被删除节点
plist->cursize--;//让链表的长度减去一
return true;
}
//尾部删除
void pop_back(LinkList*plist)
{
Erase_Pos(plist, plist->cursize);
}
//头部删除
void pop_front(LinkList*plist)
{
Erase_Pos(plist, 1);
}
//删除表中VAl节点
void remove(LinkList* plist, ElemType val)
{
ListNode* p = FindValue_Pre(plist, val);
Erase_Next(plist, p);
}
//删除表中所有的val节点
void remove_all(LinkList* plist, ElemType val)
{
assert(plist != nullptr);
ListNode* p = plist->head;
while (p->next != nullptr)
{
if (p->next->data == val)
{
Erase_Next(plist, p);
}
else
{
p = p->next;
}
}
}
//请空链表
void Clear_list(LinkList* plist)
{
assert(plist != nullptr);
while (plist->head->next != nullptr)
{
Erase_Next(plist, plist->head);
}
}
//销毁链表
void Destory_List(LinkList *plist)
{
assert(plist != nullptr);
Clear_List(plist);
Freenode(plist->head);
plist->head = nullptr;
}
//用两个指针进行查找val的前驱结点
ListNode* FindValue_pre(LinkList* plist, ElemType val)
{
assert(plist != nullptr);
ListNode* pre = plist->head;
ListNode* p = pre->next;
while (p != nullptr && p->data != val)
{
pre = p;
p=p->next;
}
if (pre->next == nullptr && p == nullptr)
{
printf("no data\n");
return nullptr;
}
return pre;
}
//用一个指针进行查找
ListNode* FindValue_pre2(LinkList* plist, ElemType val)
{
assert(plist != nullptr);
ListNode* pre = plist->head;
//ListNode* p = pre->next;
while (pre->next != nullptr && pre->next->data != val)
{
pre = pre->next;
}
if (pre->next->next == nullptr)
{
printf("no data\n");
return nullptr;
}
return pre;
}
//给定前驱结点,在其后面就插入节点val
void Insert(LinkList* plist, ListNode* pre, ElemType val)
{
assert(plist != nullptr&&pre!=nullptr);
//ListNode* s = (ListNode*)malloc(sizeof(ListNode));
//if (s == nullptr)exit(1);
ListNode* s = BuyNode();
s->data = val;
//如果pre是尾结点,直接让pre指向S即可,若不是尾结点就需要让s指向pre的后继节点,让pre指向s.
if (pre->next == nullptr)
{
pre->next = s;
plist->cursize++;
}
else
{
s->next = pre->next;
pre->next = s;
plist->cursize++;
}
return;
}
//给出前驱节点,删除pre的后继
void Erase_next(LinkList* plist, ListNode* pre)
{
assert(plist != nullptr && pre != nullptr);
if (pre->next != nullptr)
{
//如果给的是尾节点就不用进行删除
ListNode* p = pre->next;
pre->next = p->next;
free(p);
p = nullptr;
plist->cursize--;
}//做完删除一定要将节点的个数减一
}
//带头结点逆置
void Inverse(LinkList* mylist)
{
assert(mylist != nullptr);
if (mylist->cursize < 2) return;//若链表长度小于2就无需逆置
ListNode* p = mylist->head->next;//自己写一个头结点
ListNode* s = nullptr;
mylist->head->next = nullptr;
while (p != nullptr)
{
s = p;
p = p->next;
s->next = mylist->head->next;
mylist->head->next = s;
}
}
//不带头节点逆置
ListNode* reverse(ListNode* head)
{
if (head == nullptr || head->next == nullptr) return head;
ListNode* p = head->next;
head->next = nullptr;
while (p != nullptr)
{
ListNode* s = p;
p = p->next;
s->next = head;
head = s;
}
return head;
}
//插入排序,找到链表中的最小值然后将其放到相应的位置
void SelectSort(LinkList* plist)
{
assert(plist != nullptr);
if (plist->head->next == nullptr)return;
ListNode* p = plist->head->next;
while (p->next != nullptr)
{
ListNode* pmin = p;
ListNode* s = p->next;
while (s != nullptr)
{
if (s->data < pmin->data)
{
pmin = s;
}
s = s->next;
}
Swap(pmin->data, p->data);
p = p->next;
}
}
//不带头结点的递归逆置
ListNode* RevList(ListNode* pre, ListNode* p)
{
ListNode* tail = nullptr;
if (p != nullptr)
{
tail = RevList(p, p->next);
p->next = pre;
}
else
{
tail = pre;
}
return tail;
}
//带头结点的逆置
void ListResver(LinkList* plist)
{
assert(plist != nullptr);
plist->head->next = RevList(nullptr, plist->head->next);
}
//用链表实现插入排序(数组的插入排序)
void InsertSort(int* ar, int n)
{
assert(ar != nullptr);
for (int i = 1; i < n; ++i)
{
if (ar[i] < ar[i - 1])
{
int tmp = ar[i];
int j = i - 1;
do {
ar[j + 1] = ar[j];
--j;
} while (j > 0 && ar[j] > tmp);
ar[j + 1] = tmp;
}
}
}
//用链表实现插入排序
void ListInsertSort(LinkList* plist)
{
assert(plist != nullptr);
ListNode* pre = plist->head->next;//先找到链表的第一个节点
ListNode* p = pre->next;
while (p != nullptr)
{
if (p->data < pre->data)//当前节点的值小于他前驱节点的值时才开始进行插入排序
{
ListNode* tmp = p;
ListNode* s = plist->head;
do
{
if (tmp->data < s->next->data)//从链表的第一个节点开始比较,找到链表中第一个比当前节点的值大的节点然后进行插入
{
tmp->next = s->next;
s->next = tmp;
}
s = s->next;//从第一个节点开始往后面找
} while (s != p);
}
pre = p;
}
}
//将数组当做是单链表进行单向的快速排序,用两个指针,当快指针大于划分元的时候直接向后移动,当快指针小于划分元的时候,让满指针向后移动一位然后交换两个指针的值
//当快指针指向最后一个数据的时候,让慢指针的值和划分元进行比较,最后返回慢指针即为划分元的位置。
int partition(int* ar, int left, int right)
{
assert(ar != nullptr);
int i = left, j = left - 1;
int tmp = ar[i];
if (left < right)
{
while (i < right)
{
if (ar[i] <= tmp)
{
j++;
Swap(ar[i], ar[j]);
}
++i;
}
if (ar[j] < tmp)
{
Swap(ar[j], tmp);
}
}
return j;
}
ListNode* Partition(ListNode* start, ListNode* end)
{
int tmp = start->data;
ListNode* s = start;
ListNode* q = s->next;
while (q != nullptr)
{
if (q->data < tmp)
{
s = s->next;
Swap(s->data, q->data);
}
q = q->next;
}
Swap(start->data, s->data);
return s;
}
//单链表的快速排序
void List_QuickSort(ListNode* start, ListNode* end)
{
if (start != end)
{
ListNode* part = Partition(start, end);
List_QuickSort(start, part);
List_QuickSort(part->next, end);
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。