/*
构造一个带头节点的空链表1.1为单链表的指针、头指针可以标志一个
确定的单链表,算法中1前的"&"表示该变量是指针的指针的类型,实现时用*表示
*/
#include <iostream>
using namespace std;
/*
描述一个单链表
*/
typedef struct node
{
int data; //定义存储整形数据
struct node *next; //定义存储下一个数据位置的指针
}node, *linkList;
/*
首先初始化一个链表
*/
int Initlist (linkList &a)
{
if ( (a = (node*)malloc(sizeof(node))) == NULL)
return 0;
else
{
a->next =NULL;
return 1;
}
}
/*
建立一个链表。类似于往栈中存放数据。p为动态指针,始终指向未分配数据的最顶端。
head为链表的头指针,头指针值指向链表中第一个元素的存储地址。
*/
node* Create()
{
node *head = (node*)malloc(sizeof(node));//定义指向结构体的头指针
node *p;
node *s;
int x;
int cycle = 1;
p = head; //把头指针指向p
while(cycle)
{
cout<<"Please input the data"<<endl;
cin>>x; //每输入一次数据
if(x!=0)
{
s = (node*)malloc(sizeof(node));//分配一个内存地址
s->data = x; //把输入的数据传入到s所指向的地址中去
cout<<x;
p->next = s; //把分配的(指向该数据x的)内存地址保存到上一个数据的next指针中去
p = s; //让指针p重新指向当前位置
}
else
cycle = 0;
}
head = head->next; //head
p->next = NULL; //把最后一个数据的指针赋值为NULL
cout<<head->data;//最先传进去的值
return (head);//返回
}
/*
单链表测长,掌握结构体作为形参的传参方式
*/
int length(struct node *head)
{
int n = 0;
struct node *p;
p = head;
while(p!=NULL)
{
p = p->next;
n++;
}
return (n);
}
/*
单链表打印
*/
void prient(struct node *head)
{
struct node *p;
int n;
n = length(head);//获得链表的长度
p = head;
if(head != NULL)
while(p!=NULL)
{
cout<<p->data;
p=p->next;
}
}
/*
单链表删除一个节点.分为两种情况,一是删除的是头结点;二是删除节点
*/
node* deleteNode(struct node *head,int num)
//num为要删除的链表中的元素
{
struct node *p;
struct node *pFollow;
p = head ;
//找到需要删除的那个数,并且需要在链表的长度内
while(num!=p->data && p->next !=NULL)
{
pFollow = p;
p = p->next;
}
if(p->data ==num)
{
//如果删除的为第一个节点
if(p ==head)
{
head = p->next;
free(p);
}
//否则
else
{
pFollow->next = p->next;
free(p);
}
}
return (head);
}
/*
单链表的插入
插入算法有多种,比如(1)在某个数据之后插入一个新的元素
(2)在第i-1和i个数据之后插入一个新的元素
(3)在递增/减有序表中插入一个新的元素,使得生成的长度为n+1的表仍然是有序的
这里只是介绍第(2)中算法
*/
node* InsertList(struct node *head, int i, int elem)
// i 要插入的元素的位置;elem 要插入的元素
{
struct node *p;
struct node *s;
s = (node*)malloc(sizeof(node));//生成一个新的节点
p = head;
int j = 0;//计数器
//如果插入的是在头节点
while(p->next != NULL && i != j)
{
p = p->next; //指向下一个节点
j++;
}
//找到要插入的元素的位置
s->data = elem; //将新的元素插入到数据区域中
s->next =p->next;//将上一个节点指针赋值到新的指针区域
p->next =s;
return (head);
}
/*
单链表的清空
*/
node* CleanList(struct node* head)
{
struct node* p;
p = head;
while(p->next!= NULL)
{
p= p->next;
free(p);
}
return (head);
}
/*
单链表的排序。将所有的数据按有大到小的顺序重新排列,并从新输出
*/
node* SortList(struct node* head)
{
struct node *p;
int temp;
p = head;
//获得链表的长度
int n = length(head);
if(head ==NULL || head->next ==NULL)
{
return head;
}
for(int i = 1;i<n;i++) //n-1次
{
p = head;
for (int j =0;j<n-i;j++) //n-i次
{
if( (p->next)->data < p->data) //后者大于前者
{
temp = p->data; //交换值
p->data = (p->next)->data;
(p->next)->data = temp;
}
p = p->next; //指向下一个地址
}
}
return (head);
}
/*
单链表的逆置
*/
node* InverseList(struct node* head)
{
struct node *p;
p = head;
int temp;
int n = length(head);
for (int i = 1;i<n;i++) //n-1次
{
p = head;
for(int j = 0;j<n-i; j++)
{
temp = p->data;
p->data = p->next->data;
p->next->data = temp;
p = p->next;
}
}
return (head);
}
void main()
{
struct node *testNode;
struct node *newNode;
struct node *tnewNode;
struct node *knewNode;
//创建一个链表
testNode = Create();
cout<<"输出该结构体数组的长度"<<endl;
cout<<length(testNode)<<endl;
prient(testNode);
//删除一个元素
newNode=deleteNode(testNode,5);
cout<<endl;
prient(newNode);
//插入一个新的元素
InsertList(newNode, 3, 100);
cout<<endl;
prient(newNode);
//排序(有小到大)
tnewNode=SortList(newNode);
cout<<endl;
prient(tnewNode);
//逆序输出
knewNode=InverseList(tnewNode);
cout<<endl;
prient(knewNode);
}