基础知识
1.存储数据的两种方式:线性结构:数组(连续),链表(非线性)和非线性结构
链表:离散存储
1.定义:
1.n个结点离散
2.彼此通过指针相连
/3.每个结点只有一个前驱结点,每个结点只有一个后驱结点
4.首结点没有前驱结点,尾结点没有后驱结点
5.专业术语:首结点;尾结点;头结点;头指针;尾指针
首结点 1->2->3 1: 首结点,第一个有效结点
头结点:在1的前面有一个头结点;头结点的数据类型和首结点的数据类型一样;
目的:方便链表的操作;第一个有效结点之前的结点
尾结点:最后一个有效结点
头指针:指向头结点的指针变量
尾指针:指向尾结点的指针变量;尾结点的指针指向NULL;
6.确定一个链表需要几个参数?
头指针 :通过头指针可以推算出链表的其他所有信息
7.确定数组需要:首地址;有效个数;长度
8.分类
单链表:只有一个指针域
双链表:每一个结点有两个指针域
循环链表: 能够通过任何一个结点找到其他所有的结点
9.算法(伪算法)
狭义的算法是与数据的存储方式密切相关;
广义的算法是与数据的存储方式无光
泛型:
利用某种技术达到的效果就是:不同的存储方式,执行的操作方式是一样
// 遍历;
// 查找;
// 清空;
// 销毁;
// 求长度;
// 排序;
// 删除结点;
p->pnext=p->pnext->pnext(导致内存泄漏)
//内存泄漏的原因:是删除的结点忽略并没有内存释放
r=p->pnext
p->pnext=p->pnext->pnext
free®
// 插入结点;
// q->pnext=p->pnext;p->pnext=q;(r=p->next;p->next=q;q->next=r)
链表的优缺点
node 结点生成;每个结点一般有两部分:一部分是有效数字;第二个是指针域
typedef struct node
{
//数据域
int data;
//指针域
struct node* pnext;
//struct node* plast;
}NODE,*PNODE;//NODE 等价于sturct node ,pnode 等价于struct node*
*主函数 新建链表和遍历链表*
int main()
{
//创建头结点指针变量
PNODE phead = NULL;
phead = creatlist();//create_list()功能:
创建一个非循环单链表,并将该链表的头结点的地址赋值给phead
traverse_list(phead);//遍历
return 0;
}
插入链表函数
PNODE creatlist(void)
{
int len;//有效结点的个数
int val;//用来临时存放用户输入的结点的值
printf("请输入链表结点的个数");
scanf_s("%d", &len);
//分配了一个不存放有效数据的头结点
PNODE phead = (PNODE)malloc(sizeof(NODE));//创建头指针
PNODE plast=phead;//创建一个指针始终指向尾结点,并且指向头指针
plast->pnext = NULL;
//phead->pnext = plast;
//plast->pnext = NULL;
if (NULL== phead)
{
printf("内存分配失败");
exit(-1);//程序终止
}
for (int i = 0;i < len;++i)
{
printf("请输入第%d的结点的值:", i + 1);
scanf_s("%d", &val);
PNODE PNEW = (PNODE)malloc(sizeof(NODE));//创建一个临时结构体指针PNODE PNEW
if (NULL == PNEW)
{
printf("内存分配失败");
exit(-1);//程序终止
}
PNEW->data = val;//指针变量指向具体数据data
plast->pnext = PNEW;
PNEW->pnext = NULL;
plast = PNEW;//plast指向尾结点
}
return phead;
}
遍历
void traverse_list(PNODE phead)
{
PNODE p = phead->pnext;
while (NULL != p)
{
cout << p->data <<" ";
p = p->pnext;
}
printf("\n");
return;
}
自己代码`
整体风格简单清晰明了
struct node
{
int data;
struct node* next;
};
typedef struct node * pnode;
bool empty(pnode head)
{
if (head == NULL)
{
return true;
}else
{
return false;
}
}
struct node* creat_link()
{
//创建头结点的head
pnode head = (pnode)malloc(sizeof(struct node));
//创建tail尾指针,
pnode tail = head;
tail->next = NULL;
for (int i = 10;i < 20;i++)
{
//创建临时结点
pnode temp= (pnode)malloc(sizeof(struct node));
//创建结点数据
if (empty(temp))
{
printf("无法分配内存");
exit(-1);
}
temp->data = i;
temp->next = NULL;
tail->next = temp;
tail = temp;
}
return head;
}
void show_data(struct node*head)
{
//因为这里面有头结点,所以首结点地址为
head = head->next;
while (head != NULL)
{
cout << head->data << endl;
head = head->next;
}
}
int main()
{
struct node* head;
head = creat_link();
show_data(head);
}
链表排序
void sort_list(PNODE phead)
{
//struct node* head = phead->pnext;
if (is_emptys(phead))
{
cout<<"链表为空,不能进行排序"<<endl;
return;
}
PNODE p, q;
int i ,j ;
int len = length_list(phead);//获取链表的有效长度
//p=phead->pnext:获取首地址
//下一个地址为p=p->pnext
//q=p->pnext:下一个结点的地址
for(i=0,p=phead->pnext;i<len-1;++i,p=p->pnext)//比较次数
for (j = i+1,q=p->pnext;j <len;++j,q=q->pnext)//比较的对象p与q的比较
{
//cout <<"q->data; " << q->data << endl;
//结点中数据进行对比,按照降序进行排列
if (p->data > q->data)
{
int t = p->data;//t = a[i];
p->data = q->data;
q->data = t;
}
}
return;
}