1 链表
Typedef struct linkworker{
//此处Typedef 就是给结构体变量名struct linkworker取别名LINK
char id[10];
char name[10];
struct linkworker *next; //这个指针是结构体指针,只能指向这样的结构体
}LINK;
LINK w1={“0001””战士”},w2={“0002”,”法师”},w3={“0003”,”射手”},*head;
head=&w1;
w1.next=&w2;
w2.next=&w3;
w3.next=NULL;
2 链表的三要素
1、头指针 head 是用来说明链表开始了,头指针就代表链表本身,所以以后要访问链表,就要访问头指针。
2、节点(node)链表中每一个结构体变量。
3、尾指针:用来说明链表结束(它是一个空指针NULL)。
如何来创建一个链表
1:用函数来创建一个链表
返回值(创建的那个链表,实际就是要返回头指针)
返回指针的函数
typedef struct student{
Char id[10];
Char name[10];
Int age;
Struct student *Next;//这个指针是结构体指针,只能指向这样的结构体
}STU;
STU *createLink(STU a[],int n)//要返回链表实际上就是要返回头指针
//通过结构体数组来提供节点
{
STU *head;
Head=&a[0]; //表示把数组a中的第一个元素赋给头指针,让头指针指向第一个节点
//用循环n=4
a[0].Next=&a[1];
a[1].Next=&a[2];
a[2].Next=&a[3];
a[3].Next=NULL;
//用循环把前一个节点与后一个节点通过next指针联系起来
for(inti=0;i<n-1;i++)
{ //与上面的几行代码功能一样
a[i].Next=&a[i+1];
}
a[n-1].Next=NULL; //退出循环后,把尾指针作为NULL
return head; //返回头指针,实际就是链表本身
}
Void findById(STU *head,char id[]);
如何输出链表的所有节点值
void outPutLink(STU *head)//参数需要一个链表,实际就是需要头指针
{
STU *p=head;//把链表的头指针赋给指针p
printf(“学号\t姓名”);
while(p!=NULL){当访问的节点不到末尾的时候
printf(“%s\t%s”,p->id,p->name);
p=p->Next;//把指针移动到下一个节点
}
void main
{
STU a[8]={
{“s1”,”张1”},{“s2”,”张2”},{“s3”,”你好”},{“s4”,”张三”},
{“s5”,”战士”},{“s6”,”张三”},{“s7,”哈哈”},{“s8”,”法师”}},*head
,NewNode={“s9”,”八戒”,12},*pNewNode=&NewNode;
Head=createLink(a,8);
outPutLink(head);
Head=Insert(head,pNewNode);
outPutLink(head);
}
链表的查找
链表的查找(如何在链表中查找一个指定的值)如果找到就输出,找不到输出没找到。
Void findById(STU *head,char id[])
{ //在一个链表中查找指定工号
//要访问链表中的所有节点
STU *p=head;//把链表的头指针赋给p
While(p!=NULL)
{
//p就代表链表中的每一个节点,
//如果p所指向那个节点的id与我们要找的id相同则退出循环
If(strcmp(p->id,id)==0)
{
break;//说明找到了,就要退出循环
}
p=p->Next;
}
If(p=NULL)
{
printf(“找不到此人”)
}
else{
//找到了就输出指针所指向的那个节点的值
printf(“%s\t%s”,p->id,p->name);
}
}
链表的删除:
1:必须找到要删除的节点(还要保留要删除节点前的节点)
2:然后才是删除
3:该函数要返回删除后的新链表,实际上是返回头指针;
根据工号去删除对应链表中的节点
STU *delById(STU *head char id[])//第一个参数告诉是哪一个链表,第二个参数是哪一个节点
{ //必须要找的该节点
STU*p=head,*fornt;
While(p!=NULL){
If(strcmp(p->id,id)==0) break;//如果这个节点是要找的节点
//p在向后移动的过程中,首先把当前值赋给front,之后p再去移动
fornt=p;//状态保存法
p=p->Next;//移动到下一个节点
}
If(p!=NULL){ //说明找到了要删除的节点
//p前面一个节点的Next指向p后面一个节点
fornt->Next=p->next;//这里的节点其实需要释放空间malloc和free;new和delete
}
return head;
}
链表的插入
可能会插入在开头,中间,结尾。
1:找的要插入的位置
2:front->Next=&NewNode; NewNode->next=p;中间
//插入一个节点并返回插入后的链表
STU *InsertNode(STU *head, STU *pNewNode)//第一个参数告诉是哪一个链表,第二个参数是哪一个节点
{ //必须要找的该节点
STU*p=head,*fornt;
While(p!=NULL&& p->age < pNewNode->age)
{//如果发现p指向的年龄比新节点的年龄小就不断循环
//p在向后移动的过程中,首先把当前值赋给front,之后p再去移动
fornt=p;//状态保存法
p=p->Next;//移动到下一个节点
}
If(p==head)
{ //说明新节点插入在开头
pNewNode->Next=head;//新节点的Next要指向以前的head
head=pnewNode;//新的head要指向插入的节点
}
else If(p=NULL)
{ //说明新的节点插入在链表的末尾
Front->next=pnewNode;//把front的Next指向新节点
pnewNode->next=NULL;//再把新节点的Next赋值为NULL
}
else
{ //说明新的节点插入在中间
//在p的前面插入
fornt->Next=pNewNode;//把front的next指向新节点
新节点的next指向p
pNewNode->next=p;
}
else
{
return head;
}
函数模板写链表
#if 1
#include <iostream>
using namespace std;
template<class Type>
class Link
{
public:
Link();
void Insert(Type&);//插入
void Delete(Type );//删除
void Reverse();//倒置
void Print();//输出
~Link();//结点的释放
struct Node
{
Node *next;
Type* p;
};
Node *head;
};
template<class Type>
Link<Type>::Link()
{
head = NULL;
}
template<class Type>
void Link<Type>::Reverse()
{
Node * current = head ;
Node * next = NULL ;
Node * result = NULL ;
while( current != NULL )
{
next = current->next ;
current->next = result ;
result = current ;
current = next ;
}
head = result ;
}
template<class Type>
void Link<Type>::Insert(Type& t)
{
Node* temp = new Node;
temp->p = &t;
temp->next = head;
head = temp;
}
template<class Type>
void Link<Type>::Delete(Type t )
{
Node * current = head ;
while( current != NULL )
{
if( current->next != NULL &&* (current->next->p) == t )
{
Node * tmp = current->next;
current->next = current->next->next ;
delete tmp;
return ;
}
current = current->next ;
}
}
template<class Type>
void Link<Type>::Print()
{
for (Node *pp = head; pp; pp = pp->next)
{
cout << *(pp->p) << " ";
}
cout << endl;
}
template<class Type>
Link<Type>::~Link()
{
Node* pp;
while (pp = head)
{
head = head->next;
delete pp->p;
delete pp;
}
}
int main()
{
Link<double> DoubleLink;
for (int i = 1; i < 7; i++)
{
DoubleLink.Insert( * new double(i + 0.1) );
}
DoubleLink.Delete( double(2.1) );
DoubleLink.Reverse();
DoubleLink.Print();
return 0;
}
#endif
共用体和位运算
什么是共用体?所有成员都使用同一片地址单元
如何来定义共用体
union 共用体类型名
{
成员列表
};
说明:
1、共用体的定义与使用方法与结构体类似
2、结构体中各个成员都有属于自己的存储单元,而共用体中各个成员都共享一个存储单元
3、数据类型与存储单元大小的对应关系;
Int-----2个存储单元(2个字节、16位2进制)
Float---4个存储单元(64位)
Long---4个存储单元(64位)
Char---1个存储单元(8位)
Double--8个存储单元
4、结构体的大小等于结构体中所有成员所占存储单元之和
5、共用体的大小等于共用体中最大成员所占存储单元的大小
6、右边的是低字节,左边的是高字节
位运算
~ :按位求反 把0变成1,把1变成0
<<:左移 把数字向左移动,右边补0 ex: 10001<<2 --> 00100
>>:右移 把数字向右移动,左边补0 ex: 10001>>2 --> 00100
&:位与 全为1则为1,有0 为0
10010
&01110
00010
^:异或 相同为0,不同为1
10010
^01110
11100
|:位或 有1则1,全0为0
优先级别:~、<<、>>、&、^、|
Inta=3,b=6;
C=a^b<<2;
先要把10进制化成2进制(化成8位):
0000 0 0 1 1 00000 0 1 1
0000 0 1 1 0 -> ^ 0001 1 0 0 0
000110 1 1
根据优先级先执行左移