此代码实现了动态链表的????
(1)头插法、尾插法创建
(2)节点的增、删、查
(3)链表求长、逆置、排序(冒泡)和销毁
(4)附加删除和排序的优化版本
详细解释见C代码,已在Qt5上实现:????????????
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//节点
//数据域:data
//指针域:指向下一个节点,下一个节点的类型是啥呢?就是本尊啊
typedef struct node
{
int data;
struct node *next;
}Node;
void traverseList(Node *head) //遍历链表 输出内容
{
while(head->next)
{
printf("%d\n",head->next->data);
head = head->next;
}
}
Node * TailCreatList () //动态创建链表(尾插法) 在为节点插入新节点
{
Node *Head= (Node *)malloc(sizeof(Node));
if(NULL == Head)
exit(-1);
Head->next = NULL;
Node *t;
t = Head; // 初始化
int nextdata;
scanf("%d",&nextdata);
while(nextdata)
{
Node *cur;
cur = (Node *)malloc(sizeof(Node));
if(NULL == cur )
exit(-1);
cur->data = nextdata;
t->next = cur;
t = t->next;
scanf("%d",&nextdata);
}
t->next =NULL;
return Head;
}
//动态创建链表(头插法)
//头节点后边插入节点,每插入一个当成头节点
//宗旨:先让新来的节点有指向,避免打断原有的指向。
Node * HHeadCreatList()
{
Node *Head= (Node *)malloc(sizeof(Node));
if(NULL == Head)
exit(-1);
Head->next = NULL;
int nodedata;
scanf("%d",&nodedata);
while(nodedata)
{
Node *cur;
cur = (Node *)malloc(sizeof(Node));
if(NULL == cur )
exit(-1);
cur->data = nodedata;
cur->next = Head->next;
Head->next = cur;
scanf("%d",&nodedata);
}
return Head;
}
void traverseListAddress(Node *head) //遍历链表,输出每个的地址
{
while(head->next)
{
printf("%d-->%p\n",head->next->data,head->next->data);
head = head->next;
}
}
void InsertList (Node *Head,int n, int Insertdata) //在数据n后边插入数据Insertdata
{
Node *p =Head->next;
while(p)
{
if(p->data == n)
{
Node *t;
t = (Node *)malloc(sizeof(Node *));
t->data = Insertdata;
t->next = p->next;
p->next = t;
break;
}
else
p = p->next;
}
}
void insertList(Node * head,int insertData) //在头部插入一个数据
{
Node * cur = (Node *)malloc(sizeof(Node));
cur->data = insertData;
cur->next = head->next;
head->next = cur;
}
int ListLen(Node *Head) //求链表长度
{
Head = Head->next;
int len = 0;
while(Head)
{
len++;
Head = Head->next;
}
return len;
}
Node * SearchList(Node * Head,int searchdata) //查找数据,返回指针
{
Head = Head->next;
while(Head)
{
if(Head->data == searchdata)
break;
Head = Head->next;
}
return Head;
}
// 删除老版本
void DeleteData1111 (Node * Head,Node *pfind) //删除某节点 / 先遍历 得到节点的前一个节点
{
Head = Head->next;
while(Head->next != pfind)
{
Head = Head->next; //找到pfind 的前驱
}
Head->next = pfind->next;
free(pfind);
}
void DeleteData (Node * Head,Node *pfind) //删除优化。删除非尾节点的时候无需遍历!!!但是此举不适用删除最后一个节点 pfind.next = NULL
{
if(pfind->next == NULL)
{
Head = Head->next;
while(Head->next != pfind)
{
Head = Head->next; //找到pfind 的前驱
}
Head->next = pfind->next;
free(pfind);
}
else
{
Node *t = pfind->next; //先给pfind.next 找个替身再 free(t)
pfind->data = pfind->next->data; //否则最后free(pfind->next)不就吧删除之后的新序列的节点删了嘛
pfind->next = pfind->next->next;
free(t);
}
}
void reverseList(Node * Head) //链表逆置
{
Node *p = Head->next,*q;
Head->next = NULL;
while(p != NULL)
{
q = p->next;
p->next = Head->next;
Head->next = p;
p = q;
}
}
void popSortDataList (Node *Head) //链表的换值排序
{
int N = ListLen(Head);
Node *p,*q;
Head = Head->next;
for(int i=0; i<N-1; i++)
{
p = Head; //每次内重循环都是从头开始
q = p->next; //q总是指向p的下一个节点 被比较的节点
for(int j=0; j<N-1-i; j++)
{
if(p->data > q->data)
{
// p->data ^= q->data; //涉及大量的数据搬运 --> 更换指针指向
// q->data ^= p->data;
// p->data ^= q->data;
}
p = p->next;
q = q->next;
}
}
}
void popSortAddressList (Node *Head) //链表的换地址排序
{
/* 换址的注意事项:
* 1、三指针的定义的位置 放在循环的那个位置? 是放在一层循环里呢还是二层循环里边呢?
* 2、冒泡排序特别适合在此处,相邻两个数据交换(相邻链表更换指向)
* 3、(重要!)当更换指向之后的重新链表,,p和q的位序变化了,,需要重新安排次序!!!!!
* 4、更换指向的时候,注意先后次序。避免换着丢失某个节点
*/
int N = ListLen(Head);
Node *prep,*p,*q;
for(int i=0; i<N-1; i++)
{
prep = Head;
p = prep->next; //每次内重循环都是从头开始
q = p->next; //q总是指向p的下一个节点 被比较的节点
for(int j=0; j<N-1-i; j++)
{
if(p->data > q->data)
{
prep->next = q;
p->next = q->next;
q->next = p;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
p = prep->next; //p的前驱次序肯定不会变,但是 p和q 交换之后的指向变成了 prep -> q -> p
q = p->next; //所以此步骤意义在于 将更换完次序的 的p、q位序恢复到排序之前
}
prep = prep->next; //三指针同步后移一个
p = p->next;
q = q->next;
}
}
}
void destroyList(Node * Head) //销毁链表
{
Node * p = NULL;
while(Head) //有多少个 malloc 就有多少个 free
{
p = Head->next;
free(Head);
Head = p;
}
}
int main()
{
Node *Head; //尾插法创建链表
Head = TailCreatList(); //设一个头结点,creatlist返回头指针!没有输入参数
traverseList(Head);
puts("");
puts("");
popSortAddressList(Head);
traverseList(Head);
//Node *HHead; //头插法创建链表
//HHead = HHeadCreatList();
//traverseList(HHead);
return 0;
}