目录
10.5 迭代器
指针同样可以比较大小,在实际操作中可以避免使用下标对其进行控制,而是只凭两个指针就可以实现对数组的遍历。
如上图:int *begin = a;
++begin后,*begin的值从1变为2,直至while(begin > end)结束,以此类推故可以实现遍历。
10.5.1 遍历
void printArray(int *begin, int *end)
{
if(begin > end)
{
return ;
}
else
{
printf("%d\n", *begin);
printArray(begin + 1, end); //此处运用了递归
}
/* while(begin <= end)
{
printf("%d\n", *begin);
++begin;
}
*/
}
10.5.2 逆序
void swap(int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
void reverse(int *begin, int *end)
{
if(begin >= end)
{
return ;
}
else
{
swap(begin, end);
reverse(begin + 1, end - 1);
}
// while(begin < end)
// {
// swap(begin++, end--);
// }
}
10.5.3 选择排序
void sortArray(int *begin, int *end)
{
int *p = begin + 1;
for(;begin < end;++begin)
{
for(p = begin + 1;p <= end;p++)
{
if(*(begin) > *(p))
{
/* int t = *(begin);
*(begin) = *(p);
*(p) = t;*/
swap(begin, p);
}
}
}
}
10.5.4 冒泡排序
void bubbleArray(int *begin, int *end)
{
int *t = begin;
int *n = end;
for(;n > begin;--n)
{
for(t = begin;t < n;++t)
{
if(*t > *(t + 1))
{
swap(t, t + 1);
}
}
}
}
注意:要分清内层for循环开始的条件喔!
冒泡排序
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
10.5.5 快速排序
通过一轮的排序将序列分割成独立的两部分,其中前一部分序列的关键字均比后一部分关键字小。继续对长度较短的序列进行同样的分割,最后到达整体有序。在排序过程中,由于已经分开的两部分的元素不需要进行比较,故减少了比较次数,降低了排序时间。
1)先从右向左找第一个比基准数小的数,小于等于的不算。指针为p
2)再从左向右数找第一个比基准数大的数。指针为q
3)循环终止,交换这两个数。
4)重复上面三步,直至p与q重叠在一起,跳出循环。
5)调用swap函数进行begin和p交换
神奇的地方在于,经过上述过程前一部分的值都小于后一部分,与二分查找类似。
接下来通过递归调用的思想再对这两部分分别排序。
6)qSort(begin, p-1);
qSort(p + 1, end);
详细代码实现:
void qSort(int *begin, int *end)
{
if(begin > end)
{
return ; //递归调用前加上
}
int t = *begin;
int *p = begin;
int *q = end;
while(p < q)
{
while(p < q && *q >= t)
{
--q;
}
while(p < q && *p <= t)
{
++p;
}
swap(p, q);
}
swap(begin, p);
qSort(begin, p - 1);
qSort(p + 1, end);
}
10.6 字符串与指针
10.6.1 字符型数组与字符串(遍历)
字符型数组相当于一个存放字符串的容器。
利用指针实现字符数组的遍历:
void Puts(const char *s)
{
while(*s) //非0即为真
{
putchar(*s++);
}
putchar('\n');
}
易混淆:
1.
1)p当中只有字符串常量中的首地址。p可以这样赋值是因为p是一个指针变量,变量在程序运行中是可变。
2)*p 输出是:H;
3)strlen(p)是12. 因为此时p中存放的是“Hello World!”这个字符串的首地址,通过p里面存放的该字符串首地址当然可以找到该字符串,故strlen(p)为p所指向的字符串的有效字符数。
4)sizeof(p)为8.
2.
strlen(s+2)=3
strlen(p + 3)=9
3.
用栈区的指针指向字符串常量区的内容,还试图修改它,是错误的, 根本改不了。解决它,在指针变量前加const 。
10.6.2 const
- const在变量与指针前有何不同?
- )在指针变量前加const,并不是说这个指针变量本身的值不能修改,而是表示该指针变量所指向的值不能修改。
int i;
const int *p;
p = &i;
*p = 100(不行,不会改变i)
2)int * const p
是表示指针变量的值不能修改但是他所指向的值可以修改
3)常规变量有可读可写的功能,加上const修饰后则变量只可读。
10.6.3 strncpy
size_t(无符号长整型) n 从src里拷贝最多n个字符到dest里。
数比字符串多只拷贝字符串的有效字符。
char *Strncpy(char *dest, const char *src, unsigned long n)
{
char *ret = dest;
while(*src && n)
{
*dest++ = *src++;
n--;
}
*dest = 0;
return ret;
}
10.6.4 Memcpy
任何类型的地址都可以拿过来赋值给万能指针,但是万能指针不能作为指针进行指针运算。
void *Memcpy(void *dest, const void *src, unsigned long n)
{
char *p = (char *)dest;
char *q = (char *)src;
while(n)
{
*p++ = *q++;
--n;
}
return dest;
}
10.6.5 Strncat
char *Strncat(char *dest, const char *src, unsigned long n)
{
char *ret = dest;
while(*dest++)
{
}
while(*src && n)
{
*dest++ = *src++;
--n;
}
*dest = 0;
return ret;
}
10.6.6 Strncmp
int Strncmp(const char *s1, const char *s2, unsigned long n)
{
while(--n && *s1 == *s2 && *s1 && *s2)
{
++s1;
++s2;
}
return *s1 - *s2;
}