自实现链表的相关操作
对于将Node* head作为参数传入函数中后,对head的赋值,最终不会改变head的指向,因为一级指针只能改变指向的值,只有二级指针才能改变一级指针的指向
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
typedef struct node
{
int data;
struct node *next;
}Node;
//创建一个空链表
Node* createList()
{
Node* head = (Node*)malloc(sizeof(Node));
head->next = NULL;
return head;
}
//头插法插入节点
void headInsert(Node* head, int insertNumber)
{
Node* cur = (Node*)malloc(sizeof(Node));
cur->data = insertNumber;
cur->next = head->next;
head->next = cur;
}
//尾插法插入节点
void tailInsert(Node* head, int insertNumber)
{
static Node* pt = head;//为了保证pt不断变化
//main中的for循环会重复调用此函数,而不是一次插入所有节点
//所以需要一个在函数结束后也存在的指针一直指向链表的尾节点
Node* cur = (Node*)malloc(sizeof(Node));
cur->data = insertNumber;
pt->next = cur;
cur->next = NULL;
pt = pt->next;//pt=cur;
}
//遍历链表
void traverseList(Node* head)
{
head = head->next;//越过头节点
while (head != NULL)
{
printf("%d\n", head->data);
head = head->next;
}
}
//求链表的长度
int lenList(Node* head)
{
int len = 0;
head = head->next;
while (head != NULL)
{
len++;
head = head->next;
}
return len;
}
//查找节点(返回此节点的地址)
Node* searchList(Node* head,int findData)
{
head = head->next;
while (head != NULL)
{
if (findData == head->data)
{
return head;
}
head = head->next;
}
return NULL;
}
//删除节点(主要查找所要删除节点的前一个节点的地址)
void deleteList(Node* head, Node* pfind)
{
while (head->next != pfind) head = head->next;//得到前趋节点
head->next = pfind->next;//将所删节点俩边连接上
free(pfind);//释放所删节点
}
//链表的冒泡排序(值的交换)
void sortPopList_Value(Node* head, int len)//长度len相当于冒泡排序中的个数
{
Node* cur = head;//head的替身
int tmp;
for (int i = 0; i < len - 1; i++)//控制趟数
{
//每次大循环都是将cur指向头节点的下一个节点,并从cur开始往后进行比较(冒泡)
cur = head->next;
for (int j = 0; j < len - 1 - i; j++)//控制次数(不再推动比较)
{
if (cur->data > cur->next->data)//头指针的后俩个节点进行比较
{
tmp = cur->data;
cur->data = cur->next->data;
cur->next->data = tmp;
}
cur = cur->next;
//作为推动比较的条件,cur往后进一步,cur->next固然也相当于往后走一步
}
}
}
//链表的冒泡排序(指针的交换)
void sortPopList_Point(Node* head, int len)
{
Node* sh = NULL;//头指针的替身
Node* p = NULL;//第一个比较节点
Node* q = NULL;//第二个比较节点
Node* tmp = NULL;//储存地址的容器
for (int i = 0; i < len - 1; i++)
{
sh = head;
p = sh->next;
q = p->next;
for (int j = 0; j < len - 1 - i; j++)
{
if (p->data > q->data)//前一个节点值大于后一个节点值
{
//交换俩个节点
sh->next = q;
p->next = q->next;
q->next = p;
//俩个节点交换后p、q位置发生改变,需要交换p、q地址的位置
//因为需要符合 if中的判断条件 pq必须进行交换
tmp = q;
q = p;
p = tmp;
}
//不管是否发生交换三个值都需要往后走推动循环
sh = sh->next;
p = p->next;
q = q->next;
}
}
}
//链表的反转
void reverseList(Node* head)
{
Node* p;
Node* q;
p = head->next;//p指向头节点的下一个节点
head->next = NULL;//先打断链表,将链表一分为二
while (p != NULL)//判断待插入的节点是否为空
{
q = p->next;//保存p的下一个节点
//进行头插
p->next = head->next;
head->next = p;
p = q;//将保存的节点重新赋值给p进行下一次判断,p的位置不能变动
}
}
int _tmain(int argc, _TCHAR* argv[])
{
srand(time(NULL));
Node *head = createList();
for (int i=0; i < 10; i++)
{
//tailInsert(head, i);
//headInsert(head, rand()%100);
headInsert(head, i);
}
//traverseList(head);
//reverseList(head);
//printf("after reverseList:\n");
//traverseList(head);
headInsert(head, 20);//确保有data为20的节点
int len = lenList(head);
printf("链表长=%d\n", len);
traverseList(head);
printf("========================================\n");
Node* pfind = searchList(head, 20);
if (NULL == pfind)
{
printf("find none\n");
}
else
{
printf("所查节点在链表中,地址为: %p\n",pfind);//已经查询到所要节点
deleteList(head, pfind);
traverseList(head);
len = lenList(head);
//sortPopList_Value(head, len);
sortPopList_Point(head, len);
printf("冒泡排序后:\n");
traverseList(head);
}
return 0;
}